MySQL LOAD DATA INFILE 优化

MySQL Optimization for LOAD DATA INFILE

我到处都看到程序员在讨论优化最快的 LOAD DATA INFILE 插入。但是他们从不多解释他们的价值观选择等,优化取决于环境,也取决于实际的实际需求。

所以,请解释一下我的 mysql 配置文件中的最佳值是什么,以达到最快的插入速度。

我的配置,英特尔双核 @ 3.30 GHz,4Gb DDR4 RAM(windows7 说“2.16Gb 可用”,因为保留了内存)。

我的 backup.csv 文件是纯文本,大约有 50 亿个条目,因此它的文件大小高达 500Gb,就像这个方案(但十六进制字符串长度为 64):

 "sdlfkjdlfkjslfjsdlfkjslrtrtykdjf";"dlksfjdrtyrylkfjlskjfssdlkfjslsdkjf"

我的table中只有两个字段,第一个是唯一索引。 space 保存问题的 ROW-FORMAT 设置为 FIXED。出于同样的原因,字段类型设置为 BINARY(32)。

我正在使用 MyISAM 引擎。 (因为 innoDB 需要更多 space!)(MySQL 版本 5.1.41)

这是我现在打算使用的代码:

 ALTER TABLE verification DISABLE KEYS;
 LOCK TABLES verification WRITE;
 LOAD DATA INFILE 'G:\backup.csv'
      IGNORE INTO TABLE verification
      FIELDS TERMINATED BY ';' ENCLOSED BY '"' LINES TERMINATED BY '\r\n'
      (@myhash, @myverif) SET hash = UNHEX(@myhash), verif = UNHEX(@myverif);
 UNLOCK TABLES;
 ALTER TABLE verification ENABLE KEYS;

如您所见,命令 use LOAD DATA INFILE 获取纯文本值,将它们转换为 HEX(最终都是十六进制哈希值,所以...)

我听说了缓冲区大小等,以及来自 MySQL 配置文件的所有这些值。我应该改变什么,最好的价值是什么? 如您所见,我已锁定 table 并已禁用用于加快速度的键。

我还阅读了文档:

 myisamchk --keys-used=0 -rq /var/lib/mysql/dbName/tblName

在插入之前这样做也会加快速度。但真正的 tblName 是什么? (因为我有一个 .frm 文件,一个 .MYD 和一个 .MYI,所以我应该指向哪个?)

Here are the lasts short hints i did read about optimisation

编辑:忘了告诉你,一切都是本地主机。

我很确定这是验证,而不是 verification.MYD 或其他两个。 .MYD 是数据,.MYI 是索引,.frm 是模式。

字符串有多长?是十六进制吗?如果是 32 个十六进制数字,那么 UNHEX 的输出不需要 BINARY(16) 吗?

该过程的较长部分可能是 ENABLE KEYS,即何时构建索引。在它 运行ning 时执行 SHOW PROCESSLIST; -- 如果它说 "using keybuffer",杀了它,它会花很长时间。如果是说类似 "building by repair" 的内容,那么它很好 -- 它正在排序,然后有效地加载索引。

您可以通过在开始该过程之前设置 myisam_data_pointer_size=5 来节省 5GB 的磁盘空间 space。似乎还有 myisam_index_pointer_size,但它可能默认为 5,这可能适合您的情况。 (我在 2004 年左右在 ver 4.0 上遇到过一次该设置;但再也没有遇到过。)

我认为 key_buffer_size 在加载和索引期间无关紧要——因为您确实不希望它使用 key_buffer。不要将它设置得太高以至于 运行 内存不足。交换对性能来说很糟糕

所以,我终于在大约 5 小时内成功地插入了我的 500GB 数据库,其中包含超过 30 亿条条目。

我尝试了很多方法,在重建 Primary Index 时我遇到了这个错误 ERROR 1034 (HY000): Duplicate key 1 for record at 2229897540 against new record at 533925080

我现在将解释我是如何完成插入的:

  • 我用 GNU CoreUtils : sort.exe 对我的 .csv 文件进行了排序(我在 windows 上)记住这样做,你需要 1.5 倍的 csv 文件作为免费 space,对于临时文件。 (所以算上 .csv 文件,最终是 2.5 倍)
  • 您创建 table,带有索引和所有内容。
  • 执行mysqladmin flush-tables -u a_db_user -p
  • 执行myisamchk --keys-used=0 -rq /var/lib/mysql/dbName/tblName
  • 插入数据:(请勿使用 ALTER TABLE tblname DISABLE KEYS; !!!)

    LOCK TABLES verification WRITE;
    LOAD DATA INFILE 'G:\backup.csv'
        IGNORE INTO TABLE verification
        FIELDS TERMINATED BY ';'
        ENCLOSED BY '"'
        LINES TERMINATED BY '\r\n'
        (@myhash, @myverif) SET hash = UNHEX(@myhash), verif = UNHEX(@myverif);
    UNLOCK TABLES;
  • 插入数据时,通过执行myisamchk --key_buffer_size=1024M --sort_buffer_size=1024M -rqq /var/lib/mysql/dbName/tblName重建索引 (注意 -rqq,加倍 q 将通过尝试修复它们来忽略可能的重复错误(而不是在等待数小时后才停止插入!)

  • 执行mysqladmin flush-tables -u a_db_user -p

我完成了!

  • 我注意到如果 .csv 文件位于数据库以外的另一个驱动器上,速度会大大提高,对于 sort 操作,将临时文件放在另一个驱动器上也是如此。 (Read/Write 速度,因为两个数据不在同一个地方)

来源又在这里:Credits here to this solution