2009-10-20 73 views
4

我想弄清楚为什么我们的 迁移脚本中的一个永远在使用中,我们试图执行一个更新,即 从另一个表中加入以获取相关数据片段。为什么这个MySQL更新会永远持续下去?

每个表(A,B)有大约100,000行。

# now populate the ACHIEVEMENT_INSTANCE.OBJECTIVE_INSTANCE_ID 
update A a, B b 
set a.INSTANCE_ID = b.INSTANCE_ID 
where a.ID = b.ID; 

好像我们正在处理的INNER JOIN是2个表100,000×10万门, 是永远走(大概wayyyy长)之间创造了一些 型笛卡尔乘积。

根据MySQL更新默认使用内部连接不知道我们 可以使用一些其他类型的JOIN,不会那么糟糕。

MySQL documentation UPDATE

UPDATE [LOW_PRIORITY] [IGNORE] table_references 
    SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ... 
    [WHERE where_condition] 

的table_references子句列出参与加入 表。其 语法在第 12.2.8.1节“JOIN语法”中描述。这里是一个例子:UPDATE items,month SET items.price = month.price WHERE items.id = month.id;前面的 示例显示使用 逗号运算符的内部联接,但多表 UPDATE语句可以使用SELECT语句中允许的任何类型的 连接,例如LEFT JOIN为 。

+0

尝试EXPLAIN query_string并发布您的结果。 – dnagirl 2009-10-20 19:09:33

+8

你有关于a.ID和b.ID的索引吗? – Greg 2009-10-20 19:10:23

+0

为什么被标记为sql-server? – 2009-10-20 20:05:56

回答

2

由于Greg在评论中指出:

你对a.ID和b.ID的指数?

我们在这些列上没有索引。一旦我们添加它们,查询需要30秒:

create index id_idx on A(id); 
create index id_idx on B(id); 
+0

再次感谢Greg。希望我们可以将您的评论标记为“已接受的答案”。:) – MarkPowell 2009-10-20 19:27:36

+0

索引对数据库有什么样的效果,这会减少很多结果时间? – 2009-10-20 20:39:28

+0

我不是正面的,但我相信索引提供了恒定的时间查找O(n)其中一个非索引列可能必须做一个完整的表扫描基本上是一个线性搜索100,000条连接100,000条记录导致O(n^2)。 (至少我是如何用自己合理化的,哈哈) – Dougnukem 2009-10-22 13:26:55

0

不是MySQL现在支持相关子查询吗?

如果是的话,试试这个:

update A a, B b 
set a.INSTANCE_ID = (SELECT b.INSTANCE_ID FROM B b WHERE a.ID = b.ID); 

(以上假设没有为每个A A B - 如果不是你需要一个WHERE EXISTS(),以避免覆盖其他a.INSTANCE_ID用null) 。

可能是查询优化器没有选择正确的连接类型,或者存在锁定问题。

它也可能是一个索引问题 - 例如,如果一个.INSTANCE_ID有一个聚集索引。

2

尝试显式连接,看看它是否提高性能:

update A a 
join B b on a.ID = b.ID 
set a.INSTANCE_ID = b.INSTANCE_ID 
相关问题