最近一次数据迁移,需要将MySQL的数据导出、处理后导入到新表和ES。这里做个简单记录,方便后续查询。

注: 为了写文章方便及隐私安全,实际内容会有所简化。例如表结构简化、数据库连接部分全部用 xxx 表示、目录及文件名均为化名等。

实践过程

原表:

book_db 库- b_book(id,create_time,update_time,price,title,intro)

新表:

book 库- book(id,price,title,create_time,update_time)- book_ext(id,book_id,intro,create_time)

MySQL导出

mkdir -p /tmp/# 导出原始数据
mysql -hxxx -uxxx -pxxx book_db  --default-character-set=utf8  -e 'select id,create_time,update_time,price,title,intro from b_book' | sed 's/NULL//g'   > /tmp/b_book.csv

sed 's/NULL//g'是因为导出的数据有些字段存的NULL,新表不需要存储NULL,所以去掉。

导出的数据每行默认以\t分隔,第一行包含字段名。这里我们删掉第一行:

sed -i '1d' /tmp/b_book.csv

数据处理

cd /tmp/# 处理create_time,update_time,price,并生成文件 book.csv
cat b_book.csv | awk -F '\t' -v OFS=' @@@ ' '{gsub(/[-:]/," ",$2); $2=mktime($2);gsub(/[-:]/,"",$3);$3=mktime($3);$4=$4*100;$6="";print $0}' > book.csv# 生成文件 book_ext.csv
cat b_book.csv | awk -F '\t' -v OFS=' @@@ ' '{print $1,$6}' > book_ext.csv# 生成文件 book_es.csv
cat b_book.csv | awk -F '\t' -v OFS=' @@@ ' '{$4=$4*100;print $0}' > book_es.csv

因为原表里时间都是datetime格式,新表是时间戳格式,这里处理成时间戳格式。价格原表是以元为单位,这里*100是为了处理成以分为单位。

-v OFS=' @@@ '表示输出的时候每列以@@@为分隔符。原因是原表里的intro字段存储的是html,可能包含常用转义字符,这里使用@@@确保能正确分隔每列。

导入到MySQL

mysql -hxxx -uxxx -pxxx book
Load Data LOCAL InFile '/tmp/book.csv' Into Table book
character set utf8
Fields Terminated By ' @@@ ' Enclosed By '' Escaped By '' Lines Terminated By '\n'
(id,create_time,update_time,price,title);Load Data LOCAL InFile '/tmp/book_ext.csv' Into Table book_ext
character set utf8
Fields Terminated By ' @@@ ' Enclosed By '' Escaped By '' Lines Terminated By '\n'
(book_id,intro);

说明:

  • Terminated 字段分隔符(列分隔符)。一般是空格或者\t
  • Enclosed 字段括起字符。没有为空字符即可
  • Escaped 转义字符。没有为空字符即可
  • Terminated 记录分隔符(行结束符)

Into Table 代表插入,记录已存在(唯一键约束)则失败不再往下执行。Replace Into Table 代表覆盖,记录已存在则覆盖(是整条记录覆盖,没有列出的字段给默认值)。Ignore Into Table 遇到已存在直接跳过。

导入到ES

由于生产的book_es.csv文件比较大,所以这里按20000条生成一个文件,防止文件过大,ES导入失败。

cd /tmp/awk '{filename = "book_es.csv." int((NR-1)/20000) ".csv"; print >> filename}' book_es.csv

ConvertBookToEs.php是PHP脚本,生成ES批量导入的文件。见附录。执行后生成很多book_es.csv.*.csv.json文件。

php ConvertBookToEs.php

importToEs.sh是ES批量导入脚本,如下:

#!/bin/bash
for file in `ls /tmp/book_es.csv.*.csv.json`
doecho $file;curl -XPOST http://xxx:9200/book/doc/_bulk -H "Content-Type: application/json" --data-binary "@$file"  >> importToEs.log
done

执行脚本:

sh importToEs.sh

等待数分钟,便执行完毕了。

实现MySQL LOAD DATA按字段更新

为了将大量数据加载到MySQL中,LOAD DATA INFILE是迄今为止最快的选择。但是,虽然这可以以INSERT IGNOREREPLACE的方式使用,但目前不支持ON DUPLICATE KEY UPDATE

如果我们想批量更新某个字段,ON DUPLICATE KEY UPDATE如何使用LOAD DATA INFILE模拟?

stackoverflow 上有网友给了答案。步骤是:

1)创建一个新的临时表。

CREATE TEMPORARY TABLE temporary_table LIKE target_table;

2)从临时表中删除所有索引以加快速度。(可选)

SHOW INDEX FROM temporary_table;DROP INDEX `PRIMARY` ON temporary_table;
DROP INDEX `some_other_index` ON temporary_table;

3)将CSV加载到临时表中

LOAD DATA INFILE 'your_file.csv'
INTO TABLE temporary_table
Fields Terminated By '\t' Enclosed By '' Escaped By '' Lines Terminated By '\n'
(field1, field2);

4)使用ON DUPLICATE KEY UPDATE复制数据

SHOW COLUMNS FROM target_table;INSERT INTO target_table
SELECT * FROM temporary_table
ON DUPLICATE KEY UPDATE field1 = VALUES(field1), field2 = VALUES(field2);

MySQL将假定=之前的部分引用INSERT INTO子句中指定的列,第二部分引用SELECT列。

5)删除临时表

DROP TEMPORARY TABLE temporary_table;

使用SHOW INDEX FROMSHOW COLUMNS FROM此过程可以针对任何给定的表自动执行。

注:官方文档里 INSERT ... SELECT ON DUPLICATE KEY UPDATE语句被标记为基于语句的复制不安全。所以上述方案请在充分测试后再实施。详见:
https://dev.mysql.com/doc/refman/5.6/en/insert-on-duplicate.html

附录

ConvertBookToEs.php

<?php
/*** 转换wish_book为ES 批量格式(json)*///id,create_time,update_time,price,title,intro
function dealBook($file)
{$fp = fopen($file, 'r');while (!feof($fp)) {$line = explode(' @@@ ', fgets($fp, 65535));if ($line && isset($line[1])) {$arr_head = ['index' => ['_id' => (int)$line[0]]];$arr = ['id' => (int)$line[0],'create_time' => strtotime($line[1]),'update_time' => strtotime($line[2]),'price' => intval($line[3]),'title' => (string)$line[4],'intro' => (string)$line[18],];file_put_contents($file . '.json', json_encode($arr_head, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);file_put_contents($file . '.json', json_encode($arr, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);}}}try {//处理CSV文件为es bluk json格式//参考 https://www.elastic.co/guide/en/elasticsearch/reference/current/_batch_processing.html$files = glob("/tmp/book_es.csv.*.csv");if (false === $files) {exit("can not find csv file");}$pids = [];foreach ($files as $i => $file) {$pid = pcntl_fork();if ($pid < 0) {exit("could not fork");}if ($pid > 0) {$pids[$pid] = $pid;} else {echo time() . " new process, pid:" . getmypid() . PHP_EOL;dealBook($file);exit();}}while (count($pids)) {foreach ($pids as $key => $pid) {$res = pcntl_waitpid($pid, $status, WNOHANG);if ($res == -1 || $res > 0) {echo 'Child process exit,pid ' . $pid . PHP_EOL;unset($pids[$key]);}}sleep(1);}} catch (Exception $e) {$message = $e->getFile() . ':' . $e->getLine() . ' ' . $e->getMessage();echo $message;
}

参考

1、Linux命令行文本工具 - 飞鸿影~ - 博客园
https://www.cnblogs.com/52fhy/p/5836429.html
2、mysqldump 导出 csv 格式 --fields-terminated-by=, :字段分割符; - superhosts的专栏 - CSDN博客
https://blog.csdn.net/superhosts/article/details/26054997
3、Batch Processing | Elasticsearch Reference [6.4] | Elastic
https://www.elastic.co/guide/en/elasticsearch/reference/current/_batch_processing.html
4、mysql导入数据load data infile用法整理 - conanwang - 博客园
https://www.cnblogs.com/conanwang/p/5890753.html
5、MySQL LOAD DATA INFILE with ON DUPLICATE KEY UPDATE - Stack Overflow
https://stackoverflow.com/questions/15271202/mysql-load-data-infile-with-on-duplicate-key-update
6、mysql - INSERT INTO ... SELECT FROM ... ON DUPLICATE KEY UPDATE - Stack Overflow
https://stackoverflow.com/questions/2472229/insert-into-select-from-on-duplicate-key-update
7、MySQL :: MySQL 5.6参考手册:: 13.2.5.2 INSERT ... ON DUPLICATE KEY UPDATE语法
https://dev.mysql.com/doc/refman/5.6/en/insert-on-duplicate.html
8、复制表结构和数据SQL语句 - becket - 博客园
https://www.cnblogs.com/zhengxu/articles/2206894.html

MySQL导入导出实践相关推荐

  1. linux如何mysql实现导出数据库,Linux下MySQL导入导出数据库

    linux下 一.导出数据库用mysqldump命令(注意mysql的安装路径,即此命令的路径): 1.导出数据和表结构: mysqldump -u用户名 -p密码 数据库名 > 数据库名.sq ...

  2. mysql导入导出乱码问题

    linux系统中 linux默认的是utf8编码,而windows是gbk编码,所以会出现上面的乱码问题. 解决mysql导入导出数据乱码问题 首先要做的是要确定你导出数据的编码格式,使用mysqld ...

  3. 运行cmd状态下MySQL导入导出.sql文件

    MySQL导入导出.sql文件步骤如下: 一.MySQL的命令行模式的设置: 桌面->我的电脑->属性->环境变量->新建-> PATH=":path\mysq ...

  4. 大数据基础(二)hadoop, mave, hbase, hive, sqoop在ubuntu 14.04.04下的安装和sqoop与hdfs,hive,mysql导入导出

    hadoop, mave, hbase, hive, sqoop在ubuntu 14.04.04下的安装 2016.05.15 本文测试环境: hadoop2.6.2 ubuntu 14.04.04 ...

  5. mysql 导入导出数据库

    mysql 导入导出数据库 1.导出数据 // 导出test 数据库 -R 表示导出函数和存储过程,加上使导出更完整 mysqldump -u root -p -R test > test.sq ...

  6. mysql数据库导入sql文件Mysql导入导出.sql文件的方法

    mysql数据库导入sql文件:Mysql导入导出.sql文件的方法 mysql导入sql文件:Mysql导入导出.sql文件 步骤如下: 一.MYSQL的命令行模式的设置: 桌面->我的电脑- ...

  7. mysql导入导出.sql数据

    导入sql的命令:source "路径名"+/mytest_emp_dept.sql 常用source 命令 进入mysql数据库控制台, 如mysql -u root -p my ...

  8. MySQL导入导出数据和结构

    1. mysql导出数据和结构 使用mysqldump命令 1.1 导出全库 连带数据 mysqldump -u root -p app_test > app_test.sql 1.2 导出指定 ...

  9. mysql 导入导出 csv_mysql 导出导入数据 -csv

    MySql数据库导出csv文件命令: mysql> select first_name,last_name,email from account into outfile 'e://output ...

最新文章

  1. java设计模式中不属于创建型模式_23种设计模式第二篇:java工厂模式定义:工厂模式是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式...
  2. 什么是CMU Pronoucing Dictionary(CMU发音词典)
  3. DELL通过LCD简单的判别服务器的硬件故障
  4. 7个杀手级的开源监测工具
  5. 错误时自动退出bash shell脚本[重复]
  6. 不想学python-为什么自学python总是坚持不下去,这篇文章给你解答!
  7. Apache Common常用jar包
  8. QT的QFormLayout类的使用
  9. .NET/.NET Core中更清晰的堆栈跟踪
  10. 工作中的沟通及信息传递
  11. IDEA查看Java类的UML关系图
  12. 【MySQL】sql语句中exists和in有何区别?
  13. 项目方说性能达到百万TPS,如何测试它的可信度?
  14. android recyclerview item自适应高度_web前端入门到实战:css让一个盒子的高度自适应屏幕剩余的部分...
  15. css3中的border-image用法
  16. 共享锁 排他锁 是什么区别
  17. nginx的配置总结
  18. VS985破解电信4G或联通4G
  19. 计算机网络之IP报文
  20. VARCHART XGantt_v5.1用户手册:如何提供数据(.NET版)

热门文章

  1. vscode怎么快速生成html页面骨架
  2. 王者荣耀人物装备PNG153个
  3. php刮刮乐代码,手机刮刮乐HTML5代码
  4. 杰理之EMI驱动的屏幕【篇】
  5. 将毫秒转换成天、时、分、秒
  6. N多大学图书馆,里面可以找到N多密码
  7. elasticsearch-7.6.1-windows-x86_64.zip百度网盘下载
  8. 【正点原子STM32连载】第四十二章 FLASH模拟EEPROM实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1
  9. 学习笔记 | 基于FPGA的伪随机数发生器(附代码)
  10. 打造教育培训的“师育学大”——线上教育网站建设这件事