2015-04-06 29 views
0

任何人都可以給我一個關於如何優化此更新的提示MySQL查詢需要大約一分鐘的時間來處理?優化包含EXISTS的MySQL UPDATE查詢的性能

UPDATE store s 
SET reservation=1 
WHERE EXISTS (
    SELECT 1 
    FROM item i 
    WHERE s.reservation=0 
    AND s.status!=9 
    AND s.id=i.store_id 
    AND i.store_id!=0 
) 

我需要更新(設置預約= 1),在「商店」表中的所有行(這是非常大),那裏是目前預訂= 0,但它在另一個表「項目」存在的ID。表「項目」也很大,但不如「存儲」。

我不是創建高效查詢的專家,所以請原諒我,如果這只是一種完全錯誤的態度,整個事情都有一個簡單的解決方案。

感謝您的任何想法。

回答

0

它看起來像相關子查詢中的一些謂詞可以移動到外部查詢。例如,我相信這是等價的:

UPDATE store s 
    SET s.reservation = 1 
WHERE s.reservation = 0 
    AND s.status != 9 
    AND s.id != 0 
    AND EXISTS (SELECT 1 
        FROM item i 
       WHERE i.store_id = s.id 
      ) 

對於最能表現,至少,我們會希望有reservation作爲前導列上store的索引。還包括statusid列意味着可以從索引頁檢查這些條件,而無需查找表中的底層頁面。

而對於那個相關的子查詢(依賴查詢),我們希望在item上有一個索引store_id作爲主要列。

作爲另一種選擇,可考慮重新編寫相關子查詢作爲JOIN操作,例如:

UPDATE store s 
    JOIN item i 
    ON i.store_id = s.id 
    SET s.reservation = 1 
WHERE s.reservation = 0 
    AND s.status != 9 
    AND s.id != 0 

如果你正在運行MySQL 5.5或更早版本,你不能在使用UPDATE EXPLAIN聲明。我們可以得到的最接近的結果是將查詢重寫爲SELECT,並對此進行說明。 MySQL 5.6在UPDATE語句上支持EXPLAIN。

+0

感謝您的全面解答 - 將子查詢重寫爲JOIN實際執行速度要快得多 - 而不是幾分鐘就花了幾秒鐘!添加索引對於未來的操作將更加有效。 – Johnny

0

你可以嘗試使用:

UPDATE store s INNER JOIN item i ON s.id=i.store_id SET reservation=1 WHERE i.store_id!=0 AND s.reservation=0 AND s.status != 9; 

這種情況,因爲當你需要檢查「存儲」行,你不會每次都去通所有的「項目」表應工作得更快。

+0

謝謝!此查詢執行的速度比使用存在的要快得多。 – Johnny