2013-08-29 184 views
0

這是一場長達19小時的惡夢。爲什麼UPDATE JOIN查詢比SELECT JOIN查詢慢得多?

我有一個非常大的查詢,本質上需要跨幾個表連接大型數據集。在進行連接之後,我需要使用select語句中的數據更新原始表。 SELECT語句超快,UPDATE語句超慢。

這是select語句。

SELECT l.col1, 
     l.col2, 
     l.col3, 
     p.personid 
FROM table1 p 
LEFT JOIN table2 l ON (l.col1 = p.col1) 
LEFT JOIN 
    (SELECT name, 
      col AS 'col2' 
    FROM tbl3 f 
    WHERE f.col LIKE '%-F') pcf ON (pcf.col1 = p.col1) 
LEFT JOIN 
    (SELECT name, 
      col AS 'col3' 
    FROM tbl4 f 
    WHERE f.col LIKE '%-M') pcm ON (pcm.col1 = p.col1) 
WHERE p.requestid = '1928' 

現在,如果我將EXACT SAME系列的JOIN放入UPDATE上下文中,則查詢需要永久。

UPDATE table1 p 
LEFT JOIN table2 l ON (l.col1 = p.col1) 
LEFT JOIN 
    (SELECT name, 
      col AS 'col2' 
    FROM tbl3 f 
    WHERE f.col LIKE '%-F') pcf ON (pcf.col1 = p.col1) 
LEFT JOIN 
    (SELECT name, 
      col AS 'col3' 
    FROM tbl4 f 
    WHERE f.col LIKE '%-M') pcm ON (pcm.col1 = p.col1) 
SET p.col1 = l.col1, 
    p.col2 = l.col2, 
    p.col3 = l.col3 
WHERE p.requestid = '1928' 

因此......爲什麼UPDATE JOIN語句比SELECT JOIN語句花費的時間要長得多?時間更長。而且我已經嘗試過臨時表並且沒有工作。

僅供參考,我正在處理50k條記錄或更多的表格。

如果你好奇的EXPLAIN的結果,這是當我解釋了選擇查詢會發生什麼(儘管顯然你不能使用更新的解釋?)

id select_type table type possible_keys key key_len ref rows Extra 
1 PRIMARY p ALL NULL NULL NULL NULL 613246 Using where 
1 PRIMARY l eq_ref PRIMARY,name_3,name,name_2 PRIMARY 257 drilldev_db.p.lastname 1 
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 23435 
1 PRIMARY <derived3> ALL NULL NULL NULL NULL 13610 
1 PRIMARY <derived4> ALL NULL NULL NULL NULL 13053 
1 PRIMARY <derived5> ALL NULL NULL NULL NULL 8273  
1 PRIMARY <derived6> ALL NULL NULL NULL NULL 11481 
1 PRIMARY <derived7> ALL NULL NULL NULL NULL 6708  
1 PRIMARY <derived8> ALL NULL NULL NULL NULL 9588  
1 PRIMARY <derived9> ALL NULL NULL NULL NULL 5494  
1 PRIMARY <derived10> ALL NULL NULL NULL NULL 6981  
1 PRIMARY <derived11> ALL NULL NULL NULL NULL 4107  
1 PRIMARY <derived12> ALL NULL NULL NULL NULL 5973  
1 PRIMARY <derived13> ALL NULL NULL NULL NULL 3851  
1 PRIMARY <derived14> ALL NULL NULL NULL NULL 4935  
1 PRIMARY <derived15> ALL NULL NULL NULL NULL 3574  
1 PRIMARY <derived16> ALL NULL NULL NULL NULL 5793  
1 PRIMARY <derived17> ALL NULL NULL NULL NULL 4706  
17 DERIVED f ref year,gender gender 257  364263 Using where; Using temporary; Using filesort 
16 DERIVED f ref year,gender gender 257  397322 Using where; Using temporary; Using filesort 
15 DERIVED f range year,gender year 4 NULL 54092 Using where; Using temporary; Using filesort 
14 DERIVED f range year,gender year 4 NULL 54092 Using where; Using temporary; Using filesort 
13 DERIVED f range year,gender year 4 NULL 62494 Using where; Using temporary; Using filesort 
12 DERIVED f range year,gender year 4 NULL 62494 Using where; Using temporary; Using filesort 
11 DERIVED f range year,gender year 4 NULL 69317 Using where; Using temporary; Using filesort 
10 DERIVED f range year,gender year 4 NULL 69317 Using where; Using temporary; Using filesort 
9 DERIVED f ref year,gender gender 257  364263 Using where; Using temporary; Using filesort 
8 DERIVED f range year,gender year 4 NULL 94949 Using where; Using temporary; Using filesort 
7 DERIVED f ref year,gender gender 257  364263 Using where; Using temporary; Using filesort 
6 DERIVED f ref year,gender gender 257  397322 Using where; Using temporary; Using filesort 
5 DERIVED f ref year,gender gender 257  364263 Using where; Using temporary; Using filesort 
4 DERIVED f ref year,gender gender 257  397322 Using where; Using temporary; Using filesort 
3 DERIVED f ALL NULL NULL NULL NULL 37045 Using where 
2 DERIVED f ALL NULL NULL NULL NULL 37045 Using where 

謝謝!

-b

+0

你可以使用命令「explain」併發布輸出 – jcho360

+0

你如何測量「select」的「超快速」?所有結果的第一個結果還是時間到了?你可以通過添加'按col1限制1'命令來檢查需要多長時間(所有結果都需要爲'order by'生成)。 –

+0

爲什麼你有所有這些JOIN?由於它們是LEFT JOIN,它們不會限制原始表中的匹配行。 – Barmar

回答

0

讓我們考慮一下。如果您正在選擇表格的行(只是抓住它們)而不是更新每個......單行......當您瀏覽它們時,需要更長的時間?讀取n行或修改(更新)n行數?

將它與閱讀一本書的10行對比在一張紙上寫同樣的10行。哪一個需要更長時間?

我可以補充一點,你閱讀的行數與更新數量越多,差異越大。就像書本的閱讀和寫作線條會有更多差異一樣,閱讀/寫作的線條越多。

+0

我明白爲什麼需要更長的時間。我想我更感興趣的是找出爲什麼它需要*所以*更長(如果我做的東西效率低下,我可以修復)。謝謝。 –

0

如果這是你的實際陳述,你不需要第二和第三個左聯接,因爲他們不會改變結果。

順便說一句,MySQL不知道如何有效地處理「複雜」查詢:-) 如果您在臨時表中實現SELECT的結果並使用它,那麼它會快得多。

+0

我確實有一個臨時表版本,我認爲它的工作速度會更快,但它仍然不足:(。UPDATE查詢只是超級密集型的 –

+0

然後你應該顯示錶DDLs,肯定有錯誤。通過SELECT? – dnoeth

+0

什麼是表DDL?SELECT返回與我試圖匹配的原始表相同的行數(5k當它開始中斷時) –