如何加速大型MySQL更新查询?

时间:2014-04-07 17:47:17

标签: mysql performance

我试图编写我认为应该是一个相当简单的UPDATE查询,但它比我更长时间运行 期望。

我有一个collections表,还有一个名为collections_users的表。后者是一个记录集合和用户之间关联的关联表。与集合关联的用户称为"关注者"。有问题的查询使用收集记录存储每个集合的跟随者计数的快照。这是我的第一次尝试:

UPDATE collections C
SET C.follower_count_summary = (
  SELECT count(*)
  FROM collections_users CU
  WHERE CU.collection_id = C.id
);

相关信息:

  • 查询目前大约需要45秒才能运行。
  • 所有列(C.idC.follower_count_summaryCU.collection_id)都有索引。
  • collections表格有326k条记录。
  • 目前只有7 collections_users条记录,但这会增长很多。
  • MySQL版本信息:版本14.14使用readline 5.1为osx10.7(i386)分发5.5.25a

是否存在绕过这个大量查询时间的方法,或者这只是运行这样的查询所需的时间?

4 个答案:

答案 0 :(得分:2)

不是MySQL人员,但这是一个sql server通用解决方案:

DO 不进行更新。

我多次这样做,使用触发器来维持计数。这样做的好处是这种类型的查询非常胖,因为不必进行更新。

答案 1 :(得分:1)

您的尝试将对集合中的每一行执行一次子查询,这就是为什么需要很长时间。如果您使用的是mysql 5.6,则应该能够看到explain update...

我认为最好的解决方案是通过触发器维护计数或将它们快照到另一个表中(MySQL在一个查询中编写和读取同一个表是挑剔的)。然后你可以像这样快照

replace into collections_counts
 select C.id, count(1)
   from collections C
   join collection_users CU on (C.id = CU.collections_id)
  group by C.id;

然后只需在每次获取集合

时加入该表

答案 2 :(得分:1)

我可能会选择以下内容:

UPDATE collections C INNER JOIN (SELECT  CU.collection_id, 
    count(*) cu_count
FROM collections_users CU) cu2 ON C.id = cu2.collection_id
SET C.follower_count_summary =  cu2.cu_count;

但是我现在不在MySQL的前面,并且不能用EXPLAIN来仔细检查....所以这是一个猜测

欢呼声

答案 3 :(得分:0)

您是否也有C.id的索引?

我认为问题在于WHERE CU.collection_id = C.id正在为每一行执行(带有选择计数)。

P.S。 - 尝试签入执行计划,确保它有意义 - 可能是统计数据不是最新的,所以计划根本没有使用索引......