原生MySQL load data的不足,和使用过程中面临的问题
不足之处
1:load data加载方式,单线程加载,即使cpu多核,无法有效利用
2:逐行读取文本内容,并调用数据库write_row()接口插入数据。
3:导入的文本数据,如果文件过大,可能导致在主从复制延迟增大,或者MGR架构下导致binlog事务超过2G上限,引发报错。
万里数据库GreatDB && 开源GreatSQL 均支持并行load data,如何实现的呢?
1、针对load data要加载的文件,分批次加载,GreatDB 增加gdb_parallel_load_chunk_size,在执行并行导入时,根据chunk_size参数64k-128M,将文件切分加载。
2、针对原生单线程加载,无法充分利用cpu多核问题,增加并行导入最大worker线程数,新增gdb_parallel_load_workers参数控制,参数范围1-32,用户可根据cpu核心数和硬件资源按需调整。
3、增加开关gdb_parallel_load,用户按需开启并行能力。启用级别,可以是session会话级别,也可以是global 全局级别。
实际效果如何呢?
一般情况受限于master session的文件分割速度,在cpu核心充足且其它资源没有瓶颈的前提下,理论最大的加速比大概为7倍。实际在单机环境中使用时,受限于磁盘的写入速度,一般加速比为3倍左右。使用nvme写入型SSD作为存储能获取更高的加速比。万里内部实验室数据,chunk=16k,work=32 线程并发导入 10G 文本数据,实际耗时< 50s ,导入速度 238MB/s。在分布式产品3个sqlnode启用并行+并发导入峰值可达 1.4GB/s。
疑问1:实际导入过程中,如何监控,或者查看导入的各个线程的信息呢?
1、worker线程会创建新的session导入文件块,可通过show processlist看到worker线程正在执行的语句。
LOAD /*parallel load worker(chunk_no:xxx)*/ DATA INFILE 'session_id:worker_no' INTO ...其中chunk_no代表文件块的编号,每新产生一个文件块时chunk_no加一,可通过文件原始大小、gdb_parallel_load_chunk_size,chunk_no大致判断出导入进度。session_id表示输入load data语句的session_id,即master_session_id。worker_no表示启动的worker线程编号。
疑问2:启动并行导入后,若中途失败,已执行导入的文件是否可以自动回滚呢?
1、答,不能自动回滚。分批次分chunk_size导入的数据,无法自动回滚。
疑问3:如果创建的表中包含多个索引,并行导入速度是否会受影响?
1、答,会的。如果追求最快的效率导入表数据,建议索引可在导入完成之后,然后再create index 到表上。这样导入时,不用考虑多个索引数据的写入,和索引自身维护,并行更新带来的性能降低的问题。




