我有一个包含500万行的表citations
,其中包含以下信息:
Paperkey1 | Year1 | Paperkey2 | Year2
100 20
200 90
300 80
另一个表pub_year
,包含大约300万行,其中包含以下信息:
Paperkey | Year
100 2001
200 2002
20 2003
90 2004
80 2005
我想通过从表citations
获取年份值来更新表pub_year
。我使用了以下查询,但它已运行超过3个小时仍然尚未完成。
update citations T2
join pub_year T1 on T2.paperkey1= T1.paperkey
set T2.year1 = T1.year;
有谁知道它花了太长时间的主要原因是什么?如果我继续让它运行,我不确定它是否会完成。或者我的查询有问题吗? paperkey字段全部在varchar中,year字段都是整数。谢谢。
以下是运行EXPLAIN后的更新:
答案 0 :(得分:3)
第ALL
列中第二行的值为type
。这是非常非常慢的执行的原因。对于来自citations
的500万行中的每一行,它需要扫描表pub_year
的所有300万行,以便找到JOIN
子句的匹配行。索引将解决这个问题。
在表Paperkey1
的列citations
上添加索引:
ALTER TABLE `citations` ADD INDEX (`Paperkey1`);
还在表Paperkey
的列pub_year
上添加索引:
ALTER TABLE `pub_year` ADD INDEX (`Paperkey`);
如果两个表中的一个已经包含上述列的索引(或者它是多列索引中的第一列),则跳过该表;具有相同的索引并没有帮助。
创建索引后(它们将花费一些时间来完成,特别是如果同时在这些表上有其他活动),再次运行EXPLAIN
并检查结果。
您应该在第二行的ref
列中获得eq_ref
或type
。
现在UPDATE
将更快完成。它仍然需要几分钟(如果在查询期间其他进程访问表,则会更多),但是当您更新500万条记录时,这是正常的。
出于性能原因,在INNER JOIN
上建议首先放置在最终结果集中产生最小行数的表。在这种情况下,该表格为pub_year
:
UPDATE pub_year T1
INNER JOIN citations T2 ON T2.paperkey1 = T1.paperkey
SET T2.year1 = T1.year
(作为旁注,MySQL查询优化器足够聪明,可以更改查询并将表放在提供最佳执行时间的顺序中。您可以在{{1}的结果中看到来自问题的查询:表EXPLAIN
(T1
)排在第一位。)