0

基本上我的问题是我有一个包含大约 17,000,000 种产品的大表,我需要非常快速地应用大量更新。

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

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

我快速发布这 1700 万个更新的策略是在 ruby​​ 脚本中将所有这些更新加载到内存中,并将它们分组到数组散列中,这样每个 update_value 都是一个键,每个数组都是排序后的 product_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,整个数据库应该适合内存,并且有足够的增长空间。

4

2 回答 2

0

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

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

这样,它是一次通过数据库和一个 mysql 可以通过的大查询

于 2012-10-30T20:57:36.877 回答
0

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

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

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

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

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

如果需要事务操作,我可能想要有两个表,或者使用一些技巧将两个逻辑表合并到一个表中,这在上述缓存讨论的角度来看更便宜。但是,如果您不需要进行事务处理,那么缓慢的更新product_id就是要走的路。

于 2012-10-30T21:20:34.033 回答