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 速度,因为两个数据不在同一个地方)
我到处都看到程序员在讨论优化最快的 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 速度,因为两个数据不在同一个地方)