You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何多线程/多进程执行MySQL LOAD DATA INFILE反而更慢?

为什么多进程导入CSV反而比单文件慢?

核心原因

  1. 磁盘IO竞争:磁盘(哪怕是SSD)的并发写入能力有限,同时导入两个文件会让磁盘频繁切换读写位置,反而降低整体吞吐量,远不如单文件连续读写高效。
  2. MySQL内部优化被抵消:LOAD DATA INFILE本身是MySQL针对批量导入做了极致优化的命令,单线程导入时会批量写入数据、减少事务日志刷盘次数;而并发导入时,两个独立事务会触发更频繁的日志刷新,直接抵消了并发的优势。
  3. 额外开销叠加:多进程创建、每个进程单独建立数据库连接,这些零碎的开销叠加后,也会拉长总耗时。

优化方案

方案1:优化单文件导入效率(推荐)

不用拆分文件,给LOAD DATA INFILE加上前置优化配置,能大幅提升单文件导入速度:

def write_large(path):
    mydb=mysql.connector.connect(
            host='localhost',
            user='python',
            password='rvlPBO67.',
            database='test'
        )
    mycursor=mydb.cursor()
    # 临时关闭唯一键和外键检查,导入后恢复
    mycursor.execute("SET UNIQUE_CHECKS=0;")
    mycursor.execute("SET FOREIGN_KEY_CHECKS=0;")
    # 临时调整日志刷盘策略(导入完成后改回1保证数据安全)
    mycursor.execute("SET GLOBAL innodb_flush_log_at_trx_commit=2;")
    
    sql=f"LOAD DATA INFILE '{path}' INTO TABLE cereal FIELDS TERMINATED BY ',' IGNORE 1 ROWS;"
    mycursor.execute(sql)
    
    # 恢复原有配置
    mycursor.execute("SET UNIQUE_CHECKS=1;")
    mycursor.execute("SET FOREIGN_KEY_CHECKS=1;")
    mycursor.execute("SET GLOBAL innodb_flush_log_at_trx_commit=1;")
    
    mydb.commit()

另外,提前调大MySQL的innodb_log_file_size参数(需重启MySQL),比如设置为2G,能减少日志切换频率,进一步提升批量写入速度。

方案2:若坚持使用并发导入

  • 必须使用高性能SSD,机械硬盘的并发写入效率极低,完全不适合并发导入场景。
  • 调整MySQL的IO线程数:SET GLOBAL innodb_write_io_threads=8;(根据CPU核心数调整),让MySQL能更好地处理并发写入请求。
  • 避免拆分过多小文件,控制在2-4个即可,过多文件会加剧IO竞争。

方案3:用MySQL原生工具替代Python调用

直接使用mysqlimport命令行工具,它是LOAD DATA INFILE的原生封装,比Python代码调用更高效,示例命令:

mysqlimport --local --user=python --password=rvlPBO67. --fields-terminated-by=',' --ignore-lines=1 test /var/lib/mysql-files/cerealLong.csv

内容的提问来源于stack exchange,提问作者Christian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 10:54:18