1. import_table介绍

上期技术分享我们介绍了MySQL Load Data的4种常用的方法将文本数据导入到MySQL,这一期我们继续介绍另一款更加高效的数据导入工具,MySQL Shell 工具集中的import_table,该工具的全称是Parallel Table Import Utility,顾名思义,支持并发数据导入,该工具在MySQL Shell 8.0.23版本后,功能更加完善, 以下列举该工具的核心功能

  • 基本覆盖了MySQL Data Load的所有功能,可以作为替代品使用
  • 默认支持并发导入(支持自定义chunk大小)
  • 支持通配符匹配多个文件同时导入到一张表(非常适用于相同结构数据汇总到一张表)
  • 支持限速(对带宽使用有要求的场景,非常合适)
  • 支持对压缩文件处理
  • 支持导入到5.7及以上MySQL

2. Load Data 与 import table功能示例

该部分针对import table和Load Data相同的功能做命令示例演示,我们依旧以导入employees表的示例数据为例,演示MySQL Load Data的综合场景

  • 数据自定义顺序导入
  • 数据函数处理
  • 自定义数据取值
  1. ## 示例数据如下
  2. [root@10-186-61-162 tmp]# cat employees_01.csv
  3. "10001","1953-09-02","Georgi","Facello","M","1986-06-26"
  4. "10003","1959-12-03","Parto","Bamford","M","1986-08-28"
  5. "10002","1964-06-02","Bezalel","Simmel","F","1985-11-21"
  6. "10004","1954-05-01","Chirstian","Koblick","M","1986-12-01"
  7. "10005","1955-01-21","Kyoichi","Maliniak","M","1989-09-12"
  8. "10006","1953-04-20","Anneke","Preusig","F","1989-06-02"
  9. "10007","1957-05-23","Tzvetan","Zielinski","F","1989-02-10"
  10. "10008","1958-02-19","Saniya","Kalloufi","M","1994-09-15"
  11. "10009","1952-04-19","Sumant","Peac","F","1985-02-18"
  12. "10010","1963-06-01","Duangkaew","Piveteau","F","1989-08-24"
  13. ## 示例表结构
  14. 10.186.61.162:3306 employees SQL > desc emp;
  15. +-------------+---------------+------+-----+---------+-------+
  16. | Field | Type | Null | Key | Default | Extra |
  17. +-------------+---------------+------+-----+---------+-------+
  18. | emp_no | int | NO | PRI | NULL | |
  19. | birth_date | date | NO | | NULL | |
  20. | first_name | varchar(14) | NO | | NULL | |
  21. | last_name | varchar(16) | NO | | NULL | |
  22. | full_name | varchar(64) | YES | | NULL | | -- 表新增字段,导出数据文件中不存在
  23. | gender | enum('M','F') | NO | | NULL | |
  24. | hire_date | date | NO | | NULL | |
  25. | modify_date | datetime | YES | | NULL | | -- 表新增字段,导出数据文件中不存在
  26. | delete_flag | varchar(1) | YES | | NULL | | -- 表新增字段,导出数据文件中不存在
  27. +-------------+---------------+------+-----+---------+-------+

2.1 用Load Data方式导入数据

具体参数含义不做说明,需要了解语法规则及含义可查看系列上一篇文章<MySQL Load Data的多种用法>

  1. load data infile '/data/mysql/3306/tmp/employees_01.csv'
  2. into table employees.emp
  3. character set utf8mb4
  4. fields terminated by ','
  5. enclosed by '"'
  6. lines terminated by '\n'
  7. (@C1,@C2,@C3,@C4,@C5,@C6)
  8. set emp_no=@C1,
  9. birth_date=@C2,
  10. first_name=upper(@C3),
  11. last_name=lower(@C4),
  12. full_name=concat(first_name,' ',last_name),
  13. gender=@C5,
  14. hire_date=@C6 ,
  15. modify_date=now(),
  16. delete_flag=if(hire_date<'1988-01-01','Y','N');

2.2 用import_table方式导入数据

  1. util.import_table(
  2. [
  3. "/data/mysql/3306/tmp/employees_01.csv",
  4. ],
  5. {
  6. "schema": "employees",
  7. "table": "emp",
  8. "dialect": "csv-unix",
  9. "skipRows": 0,
  10. "showProgress": True,
  11. "characterSet": "utf8mb4",
  12. "columns": [1,2,3,4,5,6], ## 文件中多少个列就用多少个序号标识就行
  13. "decodeColumns": {
  14. "emp_no": "@1", ## 对应文件中的第1列
  15. "birth_date": "@2", ## 对应文件中的第2个列
  16. "first_name": "upper(@3)", ## 对应文件中的第3个列,并做转为大写的处理
  17. "last_name": "lower(@4)", ## 对应文件中的第4个列,并做转为大写的处理
  18. "full_name": "concat(@3,' ',@4)", ## 将文件中的第3,4列合并成一列生成表中字段值
  19. "gender": "@5", ## 对应文件中的第5个列
  20. "hire_date": "@6", ## 对应文件中的第6个列
  21. "modify_date": "now()", ## 用函数生成表中字段值
  22. "delete_flag": "if(@6<'1988-01-01','Y','N')" ## 基于文件中第6列做逻辑判断,生成表中对应字段值
  23. }
  24. })

3. import_table特定功能

3.1 多文件导入(模糊匹配)

  1. ## 在导入前我生成好了3分单独的employees文件,导出的结构一致
  2. [root@10-186-61-162 tmp]# ls -lh
  3. 总用量 1.9G
  4. -rw-r----- 1 mysql mysql 579 3 24 19:07 employees_01.csv
  5. -rw-r----- 1 mysql mysql 584 3 24 18:48 employees_02.csv
  6. -rw-r----- 1 mysql mysql 576 3 24 18:48 employees_03.csv
  7. -rw-r----- 1 mysql mysql 1.9G 3 26 17:15 sbtest1.csv
  8. ## 导入命令,其中对对文件用employees_*做模糊匹配
  9. util.import_table(
  10. [
  11. "/data/mysql/3306/tmp/employees_*",
  12. ],
  13. {
  14. "schema": "employees",
  15. "table": "emp",
  16. "dialect": "csv-unix",
  17. "skipRows": 0,
  18. "showProgress": True,
  19. "characterSet": "utf8mb4",
  20. "columns": [1,2,3,4,5,6], ## 文件中多少个列就用多少个序号标识就行
  21. "decodeColumns": {
  22. "emp_no": "@1", ## 对应文件中的第1列
  23. "birth_date": "@2", ## 对应文件中的第2个列
  24. "first_name": "upper(@3)", ## 对应文件中的第3个列,并做转为大写的处理
  25. "last_name": "lower(@4)", ## 对应文件中的第4个列,并做转为大写的处理
  26. "full_name": "concat(@3,' ',@4)", ## 将文件中的第3,4列合并成一列生成表中字段值
  27. "gender": "@5", ## 对应文件中的第5个列
  28. "hire_date": "@6", ## 对应文件中的第6个列
  29. "modify_date": "now()", ## 用函数生成表中字段值
  30. "delete_flag": "if(@6<'1988-01-01','Y','N')" ## 基于文件中第6列做逻辑判断,生成表中对应字段值
  31. }
  32. })
  33. ## 导入命令,其中对要导入的文件均明确指定其路径
  34. util.import_table(
  35. [
  36. "/data/mysql/3306/tmp/employees_01.csv",
  37. "/data/mysql/3306/tmp/employees_02.csv",
  38. "/data/mysql/3306/tmp/employees_03.csv"
  39. ],
  40. {
  41. "schema": "employees",
  42. "table": "emp",
  43. "dialect": "csv-unix",
  44. "skipRows": 0,
  45. "showProgress": True,
  46. "characterSet": "utf8mb4",
  47. "columns": [1,2,3,4,5,6], ## 文件中多少个列就用多少个序号标识就行
  48. "decodeColumns": {
  49. "emp_no": "@1", ## 对应文件中的第1列
  50. "birth_date": "@2", ## 对应文件中的第2个列
  51. "first_name": "upper(@3)", ## 对应文件中的第3个列,并做转为大写的处理
  52. "last_name": "lower(@4)", ## 对应文件中的第4个列,并做转为大写的处理
  53. "full_name": "concat(@3,' ',@4)", ## 将文件中的第3,4列合并成一列生成表中字段值
  54. "gender": "@5", ## 对应文件中的第5个列
  55. "hire_date": "@6", ## 对应文件中的第6个列
  56. "modify_date": "now()", ## 用函数生成表中字段值
  57. "delete_flag": "if(@6<'1988-01-01','Y','N')" ## 基于文件中第6列做逻辑判断,生成表中对应字段值
  58. }
  59. })

3.2 并发导入

在实验并发导入前我们创建一张1000W的sbtest1表(大约2G数据),做并发模拟,import_table用threads参数作为并发配置, 默认为8个并发.

  1. ## 导出测试需要的sbtest1数据
  2. [root@10-186-61-162 tmp]# ls -lh
  3. 总用量 1.9G
  4. -rw-r----- 1 mysql mysql 579 3 24 19:07 employees_01.csv
  5. -rw-r----- 1 mysql mysql 584 3 24 18:48 employees_02.csv
  6. -rw-r----- 1 mysql mysql 576 3 24 18:48 employees_03.csv
  7. -rw-r----- 1 mysql mysql 1.9G 3 26 17:15 sbtest1.csv
  8. ## 开启threads为8个并发
  9. util.import_table(
  10. [
  11. "/data/mysql/3306/tmp/sbtest1.csv",
  12. ],
  13. {
  14. "schema": "demo",
  15. "table": "sbtest1",
  16. "dialect": "csv-unix",
  17. "skipRows": 0,
  18. "showProgress": True,
  19. "characterSet": "utf8mb4",
  20. "threads": "8"
  21. })

3.3 导入速率控制

可以通过maxRatethreads来控制每个并发线程的导入数据,如,当前配置线程为4个,每个线程的速率为2M/s,则最高不会超过8M/s

  1. util.import_table(
  2. [
  3. "/data/mysql/3306/tmp/sbtest1.csv",
  4. ],
  5. {
  6. "schema": "demo",
  7. "table": "sbtest1",
  8. "dialect": "csv-unix",
  9. "skipRows": 0,
  10. "showProgress": True,
  11. "characterSet": "utf8mb4",
  12. "threads": "4",
  13. "maxRate": "2M"
  14. })

3.4 自定义chunk大小

默认的chunk大小为50M,我们可以调整chunk的大小,减少事务大小,如我们将chunk大小调整为1M,则每个线程每次导入的数据量也相应减少

  1. util.import_table(
  2. [
  3. "/data/mysql/3306/tmp/sbtest1.csv",
  4. ],
  5. {
  6. "schema": "demo",
  7. "table": "sbtest1",
  8. "dialect": "csv-unix",
  9. "skipRows": 0,
  10. "showProgress": True,
  11. "characterSet": "utf8mb4",
  12. "threads": "4",
  13. "bytesPerChunk": "1M",
  14. "maxRate": "2M"
  15. })

4. Load Data vs import_table性能对比

  • 使用相同库表
  • 不对数据做特殊处理,原样导入
  • 不修改参数默认值,只指定必备参数
  1. -- Load Data语句
  2. load data infile '/data/mysql/3306/tmp/sbtest1.csv'
  3. into table demo.sbtest1
  4. character set utf8mb4
  5. fields terminated by ','
  6. enclosed by '"'
  7. lines terminated by '\n'
  8. -- import_table语句
  9. util.import_table(
  10. [
  11. "/data/mysql/3306/tmp/sbtest1.csv",
  12. ],
  13. {
  14. "schema": "demo",
  15. "table": "sbtest1",
  16. "dialect": "csv-unix",
  17. "skipRows": 0,
  18. "showProgress": True,
  19. "characterSet": "utf8mb4"
  20. })

可以看到,Load Data耗时约5分钟,而import_table则只要不到一半的时间即可完成数据导入,效率高一倍以上(虚拟机环境磁盘IO能力有限情况下)

5. 技术总结

  • import_table包含了Load Data几乎所有的功能
  • import_table导入的效率比Load Data更高
  • import_table支持对导入速度,并发以及每次导入的数据大小做精细控制
  • import_table的导入进度报告更加详细,便于排错及时间评估,包括
    • 导入速度
    • 导入总耗时
    • 每批次导入的数据量,是否存在Warning等等
    • 导入最终的汇总报告

MySQL Shell import_table数据导入的更多相关文章

  1. sqoop用法之mysql与hive数据导入导出

    目录 一. Sqoop介绍 二. Mysql 数据导入到 Hive 三. Hive数据导入到Mysql 四. mysql数据增量导入hive 1. 基于递增列Append导入 1). 创建hive表 ...

  2. docker中mysql数据库的数据导入和导出

    导出数据 查看下 mysql 运行名称 docker ps 结果:  执行导出(备份)数据库命令: 由第一步的结果可知,我们的 mysql 运行在一个叫 mysql_server 的 docker ...

  3. mysql恢复和数据导入的问题(ERROR 2006 (HY000) at line 1016: MySQL server has gone away)

    今天在上班过程中需要将一个1.3G的数据库sql文件导入到mysql数据库中去,在执行过程遇到了一些问题,执行到一半时报错,错误如下 ERROR 2006 (HY000) at line 1016: ...

  4. MySQL 5.6数据导入报 GTID 相关错误

    从阿里云备份数据后还原到本地,用命令行 mysql -uroot -p --default-character-set=<character> -f <dbname> < ...

  5. mysql5.x升级到mysql5.7后导入之前数据库date出错的快速解决方法【mysql低版本数据导入到高版本出错的解决方法】

    mysql5.x升级至mysql5.7后导入之前数据库date出错,这是由于MySQL的sql_mode的影响,解决方法如下所示: [具体参考:mysql的sql_mode详解]修改mysql5.7的 ...

  6. 利用python将mysql中的数据导入excel

    Python对Excel的读写主要有xlrd.xlwt.xlutils.openpyxl.xlsxwriter几种. 如下分别利用xlwt和openpyxl将mysql数据库中查询的数据保存到exce ...

  7. mysql的csv数据导入与导出

    # 需要station_realtime存在 load data infile 'd:/xxxx/station_realtime2013_01.csv' into table `station_re ...

  8. Mysql学习_02_mysql数据导入导出

    二.参考资料 1.MySQL 数据导出

  9. Mysql提升大数据导入速度的绝妙方法

    一.对于Myisam类型的表,可以通过以下方式快速的导入大量的数据.      ALTER TABLE tblname DISABLE KEYS;     loading the data     A ...

随机推荐

  1. Android系统编程入门系列之清单文件

    在上一篇文章中已经提到,Android系统加载应用程序之后,首先会读取该应用程序的AndroidManifest.xml清单文件,之后根据该清单文件加载后边的东西.所以要开发应用程序,自然要先知道清单 ...

  2. 【Azure 应用服务】Azure Function集成虚拟网络,设置被同在虚拟网络中的Storage Account触发,遇见Function无法触发的问题

    一切为了安全,所有的云上资源如支持内网资源访问,则都可以加入虚拟网络 问题描述 使用Azure Function处理Storage Account中Blob 新增,更新,删除等情况.Storage A ...

  3. VS 2017 RC .net core ef+ MySql 出现错误

    在di注入时会出现错误 MySql.Data.EntityFrameworkCore.Storage.Internal.MySQLCommandBuilderFactory..ctor(ISensit ...

  4. 为Centos系统打补丁

    4.1.操作系统打补丁: 1.centos更新说明: centos 官方没有发布关于centos操作系统的补丁. centos 操作系统更新可以参考如下建议. 2.更新操作系统软件包,操作系统版本.内 ...

  5. 17、ansible配置管理

    17.1.前言: 1.说明: ansible是自动化运维工具,基于Python开发,实现了批量系统配置.批量程序部署.批量运行命令等功能. ansible是基于模块工作的,本身没有批量部署的能力,真正 ...

  6. 6、基本数据类型(list)

    6.1.列表: 1.li = [1, 12, 9, "age", ["孙子涵", ["19", 10], "张涵予"], ...

  7. POJ 2084 Game of Connections 卡特兰数

    看了下大牛们的,原来这题是卡特兰数,顺便练练java.递归式子:h(0)=1,h(1)=1   h(n)= h(0)*h(n-1) + h(1)*h(n-2) + ... + h(n-1)h(0) ( ...

  8. 如何消除inline-block元素之间的间隙?

    一.问题现象 在CSS布局中,如果我们想要将多个行内块元素并排,会发现同行显示的inline-block元素之间会出现一定的空隙,这就是换行符/空格导致的,叫做换行符/空格间隙. 1 <!DOC ...

  9. 深入理解 SynchronizationContext

    深入理解 SynchronizationContext 目录 深入理解 SynchronizationContext SynchronizationContext(后续以SC简称) 是什么? 1.1 ...

  10. 如何快速实现一个虚拟 DOM 系统

    虚拟 DOM 是目前主流前端框架的技术核心之一,本文阐述如何实现一个简单的虚拟 DOM 系统. 为什么需要虚拟 DOM? 虚拟 DOM 就是一棵由虚拟节点组成的树,这棵树展现了真实 DOM 的结构.这 ...