2009-10-20 75 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 
相關問題