【问题标题】:update join table taking a very long time更新连接表需要很长时间
【发布时间】:2015-01-12 11:02:19
【问题描述】:

我有一个表 citations 有 500 万行,其中包含以下信息:

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

我想通过从表 pub_year 中获取年份值来更新表 citations。我使用了以下查询,但它已经运行了 3 个多小时,但仍未完成。

update citations T2

join pub_year T1 on T2.paperkey1= T1.paperkey

set T2.year1 = T1.year;

有没有人知道它花费太长时间的主要原因是什么?如果我继续让它运行,我不确定它是否会完成。还是我的查询有问题? paperkey 字段都是 varchar,而 year 字段都是整数。谢谢。

这是运行 EXPLAIN 后的更新:

【问题讨论】:

  • 你在加入的列上有索引吗?
  • @barmar 我唯一拥有的是纸钥匙,这是我从原始数据集中获得的钥匙。我从来没有尝试过对此应用索引。你的意思是我必须使用索引转换纸键吗?
  • 运行 EXPLAIN SELECT * FROM citations T2 JOIN pub_year T1 ON T2.paperkey1 = T1.paperkey 并使用结果更新问题。
  • @axiac 我用解释查询结果截图更新了问题
  • 有paperkey3吗?

标签: mysql performance jointable


【解决方案1】:

第二行在type 列中具有值ALL。这是执行非常非常缓慢的原因。对于来自citations 的500 万行中的每一行,它需要扫描表pub_year 的所有300 万行,以便找到JOIN 子句的匹配行。索引会解决这个问题。

在表citations的列Paperkey1上添加索引:

ALTER TABLE `citations` ADD INDEX (`Paperkey1`);

还在表 pub_year 的列 Paperkey 上添加索引:

ALTER TABLE `pub_year` ADD INDEX (`Paperkey`);

如果两个表中的一个已经包含上述列的索引(或者它是多列索引中的第一列),则跳过该表;具有相同的索引没有帮助。

创建索引后(它们需要一些时间才能完成,特别是如果这些表同时还有其他活动),再次运行EXPLAIN 并检查结果。 您应该在第二行的type 列中获得refeq_ref

现在UPDATE 将更快地完成。仍然需要几分钟(如果在查询期间其他进程访问表,则甚至更长时间),但是当您更新 500 万条记录时,这没问题。

出于性能原因,在INNER JOINs 上,建议将在最终结果集中产生最少行数的表放在首位。在这种情况下,该表是pub_year

UPDATE pub_year T1
INNER JOIN citations T2 ON T2.paperkey1 = T1.paperkey
SET T2.year1 = T1.year

(附带说明一下,MySQL 查询优化器足够智能,可以更改查询并将表按照提供最佳执行时间的顺序排列。您可以在 EXPLAIN 查询的结果中看到这一点从问题:表T1pub_year)排在第一位。)

【讨论】:

  • 效果非常好!非常感谢。但是,我发现有些年份仍然具有空值,而实际上它们存在于另一个表中。我想知道这种问题的原因是什么。
  • 在运行 UPDATE 之前,您可以将其转换为 SELECT 以了解它将修改多少行。保留表格和JOINs,保留WHERE 条件,删除SET 子句,在SELECT 中添加相关字段的COUNT()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多