我想导入维基百科数据库。 Wikipedia Dumps
我更改了一些Innodb设置:
innodb_buffer_pool_size = 4G
innodb_log_file_size=8G
innodb_log_buffer_size=512M
innodb_write_io_threads = 16
innodb_flush_log_at_trx_commit = 0
max_allowed_packet=256M
此图显示每个Sql语句的时间成本。
sql语句是这样的:插入templatelinks
值(...),(...),(...),(...)......每一个sql语句&#39 ; s大小为1MB。
为什么第1300到第1400个sql会花费这么多时间?
更多信息:
核心代码:
JdbcTemplate jdbcTemplate=new JdbcTemplate(mDatasour);
while (it.hasNext()){
jdbcTemplate.getDataSource().getConnection().setAutoCommit(false);
jdbcTemplate.execute("SET UNIQUE_CHECKS=0; ");
jdbcTemplate.execute("SET FOREIGN_KEY_CHECKS=0; ");
String line=it.nextLine();
if(line==null||line.length()==0){
continue;
}
jdbcTemplate.execute(line);
jdbcTemplate.execute("commit;");
答案 0 :(得分:1)
优化代码
将常量东西拉出循环。使用自动提交以避免需要发出COMMIT
。
jdbcTemplate.getDataSource().getConnection().setAutoCommit(true); -- Note
jdbcTemplate.execute("SET UNIQUE_CHECKS=0; ");
jdbcTemplate.execute("SET FOREIGN_KEY_CHECKS=0; ");
while (it.hasNext()){
String line=it.nextLine();
if(line==null||line.length()==0){
continue;
}
jdbcTemplate.execute(line);
}
较小的块
停止1000行或1MB的构建线,以较小者为准。除此之外,您还可以减少回报,并强调撤消日志。
摆脱多余的独特
Drop UNIQUE(from, namespace, title)
对于具有相同列列表的PRIMARY KEY
是多余的。这将减少插入工作量,因为必须在INSERT
期间检查所有唯一索引。
更改缓冲
阅读“更改缓冲”。它本质上是非唯一索引的延迟(和优化)编写,您似乎有两个。在大量插入期间的某个时刻,更改缓冲区已满,必须刷新。这种冲洗是在后台进行的,所以我无法解释尖峰的严重程度。
我怀疑在加载了大约1/3的表后,更改缓冲区得到了太多的积压,这导致了打嗝。
传入行的顺序
需要考虑的其他事项......正在编写的行的顺序是什么?如果它们是以PK顺序编写的,则每个INSERT进入PK(和数据)(以及冗余UNIQUE索引)所需的I / O非常少。您的图表似乎通过I / O开头很长时间来显示这一点。
但是,二级索引(通过更改缓冲区处理)可能非常随机。 (我不知道from
指的是什么。)这导致了很多“读 - 修改 - 写”动作来更新两个二级索引的索引块。
由于PK +数据不需要buffer_pool,但二级索引不需要,考虑调整innodb_change_buffer_max_size
,默认为“为更改缓冲区预留的buffer_pool的25%”。
刷新到磁盘
另一个问题:写入PK +数据不需要刷新到磁盘,直到超过“innodb_max_dirty_pages_pct - 默认为buffer_pool的90%”。同样,这与早期的低I / O一致。
了解这两个设置,玩弄它们,然后写一篇博文。你将成为这方面的专家。
答案 1 :(得分:1)
对于innodb_buffer_pool_size = 4G,在为innodb_change_buffer_max_size预留25%后,您的有效池大小为3G。
您的innodb_io_capacity和innodb_io_capacity_max可能会被提升以利用今天的硬盘容量。从Microsoft下载sqlio.exe可以帮助您确定适用于HDD的16384(MySQL)数据块大小的限制。
添加RAM对于将数据保存在内存中更为合适。