Mysql InnoDB并快速应用大量更新

时间:2012-10-30 20:50:58

标签: mysql ruby database innodb

基本上我的问题是我有一个大约17,000,000个产品的大表,我需要快速应用一堆更新。

该表有30列,其id设置为int(10)AUTO_INCREMENT。

我有另一个表存储了此表的所有更新,这些更新必须预先计算,因为它们需要花费几天的时间来计算。此表的格式为[product_id int(10),update_value int(10)]。

我正在采取的快速发布这1700万个更新的策略是将所有这些更新加载到ruby脚本的内存中,并将它们分组到数组的散列中,以便每个update_value都是一个键,每个数组都是一个列表sort_id的分类。

{ 
   150: => [1,2,3,4,5,6],
   160: => [7,8,9,10]
}

然后以

的格式发布更新
UPDATE product SET update_value = 150 WHERE product_id IN (1,2,3,4,5,6);
UPDATE product SET update_value = 160 WHERE product_id IN (7,8,9,10);

我很确定我正确地做到了这一点,因为在有条件的product_id批次上发布更新应该是使用mysql / innodb进行更新的最佳方式。

我遇到了一个奇怪的问题,虽然我在测试时更新了大约1300万条记录,但这只花了大约45分钟。现在我正在测试更多数据,大约1700万条记录,更新时间接近120分钟。我本来期望在某种程度上减速,但不会达到我所看到的程度。

关于我如何加快这一速度或者使用这个更大的记录集可能会减慢我的速度的任何建议?

就服务器规格而言,它们非常好,大量的内存/ CPU,整个数据库应该适合内存,并有足够的发展空间。

2 个答案:

答案 0 :(得分:0)

您可以尝试使用mysql的多表更新语法

update product, sometable SET product.update_value=sometable.value WHERE product_id=sometable.whatever;

这样就可以通过数据库进行单次传递,而mysql可以通过单个大查询进行研究

答案 1 :(得分:0)

我认为您需要仔细设计索引和数据页面访问权限。

假设查询上的product_id s'分布是随机的,则每个更新SQL都将导致随机索引页访问。当然,索引页访问之后的数据页访问也是随机的。如果您希望快速运行所有更新,则需要将所有索引页都放在内存中(至少)。因此,这不是一组快速的更新操作。

如果我正在设计它并且更新不需要是交易的, 我将按照product_ids逐个更新所有行,而不是在事务中:

UPDATE product SET update_value = 150 WHERE product_id = 1
UPDATE product SET update_value = 150 WHERE product_id = 2
...

由于它会导致索引页面和数据页面顺序读取/更新,因此该方案可能需要更长时间的更新,但在缓存管理的角度来看要便宜很多。当然, 对数据库的总体影响是最小的,因此除了更新之外的操作(如来自客户的查询)不会降级。

如果需要事务操作,我可能想要有两个表,或者使用一些技巧将两个逻辑表放到一个表中,这在上面的缓存讨论的观点中更便宜。但是,如果您不需要是事务性的,那么每product_id的慢速更新是可行的。