Jam*_*mes 5 mysql myisam bulkinsert
这里有一个问题,如何正确配置mysql(myisam)以便快速执行批量插入(加载数据infile).
有6个Gb文本文件要导入,15个行,16个列(一些int,一些varchar(255),一个varchar(40),一个char(1)一些datetime,一个mediumtext).
相对my.conf设置:
key_buffer = 800M
max_allowed_packet = 160M
thread_cache_size = 80
myisam_sort_buffer_size = 400M
bulk_insert_buffer_size = 400M
delay_key_write = ON
delayed_insert_limit = 10000
Run Code Online (Sandbox Code Playgroud)
有三个索引 - 一个主要(autincrement int),一个唯一int和一个唯一varchar(40).
问题是在执行load data infile命令后,快速导入前3个数据(基于table.myd增加的大小 - 5-8 mb/s),但是超过3020 Mb的uppon限制了导入速度大大减少 - table.myd的大小增加了0.5mb/s.我注意到,导入过程会Key_blocks_unused因为排空到零而减慢.这些是mysql> show status like '%key%';导入开头的输出:
mysql> show status like '%key%';
+------------------------+---------+
| Variable_name | Value |
+------------------------+---------+
| Com_preload_keys | 0 |
| Com_show_keys | 0 |
| Handler_read_key | 0 |
| Key_blocks_not_flushed | 57664 |
| Key_blocks_unused | 669364 |
| Key_blocks_used | 57672 |
| Key_read_requests | 7865321 |
| Key_reads | 57672 |
| Key_write_requests | 2170158 |
| Key_writes | 4 |
+------------------------+---------+
10 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
这就是它在3020Mb限制之后的样子,即当它key_blocks_unused降到零时,那就是批量插入过程变得非常慢的时候:
mysql> show status like '%key%';
+------------------------+-----------+
| Variable_name | Value |
+------------------------+-----------+
| Com_preload_keys | 0 |
| Com_show_keys | 0 |
| Handler_read_key | 0 |
| Key_blocks_not_flushed | 727031 |
| Key_blocks_unused | 0 |
| Key_blocks_used | 727036 |
| Key_read_requests | 171275179 |
| Key_reads | 1163091 |
| Key_write_requests | 41181024 |
| Key_writes | 436095 |
+------------------------+-----------+
10 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
根据我的理解,问题非常清楚 - 索引存储在缓存中,但是一旦缓存填满,索引就会逐个写入磁盘,这很慢,因此所有进程都会变慢.如果我禁用基于varchar(40)列的唯一索引,因此,所有索引都适合Key_blocks_used(我猜这是直接依赖的变量key_buffer,不是吗?),所有批量导入都是成功的.所以,我很好奇,如何让mysql立即将所有Key_blocks_used数据放入磁盘,并释放Key_blocks_used?我知道它可能正在进行一些即时排序,但我仍然认为应该可以进行一些缓存的RAM磁盘同步,以便成功管理索引,即使它们并非全部适合内存缓存.所以我的问题是" 如何配置mysql以便批量插入可以避免在(几乎)每个索引上写入磁盘,即使所有索引都不适合缓存? "最后也是如此 - 对于给定的,delay_key_write设置为1表,虽然它没有添加任何加速,与它被禁用时相比.
感谢任何想法,想法,解释和RTM提前!(:
还有一个小问题 - 在Key_blocks_unused获得0 之前,我将如何计算多少varchar(40)索引适合缓存?
如Mysql docs所述,PS禁用索引$myisamchk --keys-used=0 -rq /path/to/db/tbl_name然后重新启用它们是一种已知的解决方案,它可以工作,但只有在批量插入空表时才有效.当表中已有数据时,必须进行索引唯一性检查,因此禁用索引不是解决方案.$myisamchk -rq /path/to/db/tbl_name
小智 5
当您使用"加载数据infile"导入数据时,我认为mysql逐个执行插入,并且每次插入时,它都会尝试更新索引文件.MYI,这可能会因为消耗bot I/O而减慢导入速度和每个插入的CPU资源.
您可以做的是将4个文件添加到导入文件中以禁用表的键并在insert语句的末尾启用它,您应该看到差异.
LOCK TABLES tableName WRITE;
ALTER TABLE tableName DISABLE KEYS;
----
your insert statement from go here..
----
ALTER TABLE tableName ENABLE KEYS
UNLOCK TABLES;
Run Code Online (Sandbox Code Playgroud)
如果您不想编辑数据文件,请尝试使用mysqldump获取正确的转储文件,并且不应该使用导入数据遇到这种缓慢的问题.
##Dump the database
mysqldump databaseName > database.sql
##Import the database
mysql databaseName < database.sql
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助!
| 归档时间: |
|
| 查看次数: |
4071 次 |
| 最近记录: |