2012-06-25 147 views
0

我一直在負責支持的客戶端慢得令人痛苦的應用程序。我啓用了MySQL slow_query_log並發現了一些似乎是罪魁禍首的查詢。我對這個查詢做了些什麼感到有點困惑,但任何關於如何重寫這個的建議都會有所幫助。很慢執行MySQL查詢

SELECT 
    table_a.id AS table_a_id_1, 
    table_a2.id AS table_a_id_2 
FROM 
    table_a, 
    table_b 
LEFT JOIN 
    table_a AS table_a2 
ON 
    table_a.value = table_a2.value 
WHERE 
    table_a.value_id = 112 AND 
    table_a2.value_id = 113 AND 
    table_a.status != table_a2.status AND 
    table_a.id = table_b.id; 

對我來說,它看起來像查詢從單個表中選擇相同的數據兩次,然後做與選定的一些數據比較,以及執行與表-B聯接爲好。這裏是MySQL引用這個查詢執行的日誌。

Query_time: 160.854398 
Lock_time: 0.000139 
Rows_sent: 12 
Rows_examined: 10339025 

任何建議你可以提供將是有益的!

+0

我甚至不認爲這個查詢是有效的......你確定它運行正確嗎?在發佈之前是否對查詢進行了任何更改? –

+0

我也不認爲它是有效的,它對我來說看起來很奇怪。但是,它運行時不會產生錯誤並返回行。我對查詢做的唯一更改是用table_a和table_b ...替換表名。 我會檢查,看看是否我可以張貼實際的完整的查詢,如果你認爲這將有助於。這真的更令人困惑......哈哈! –

+1

這是一個不好的極端思想結合顯式和隱式連接(使用隱式連接在所有的是SQL反模式)。只需修復以使用明確的連接即可獲得幫助,那麼您需要修復查詢中出現錯誤的部分。在@ GordonLinoff的回答中看到我的評論。 – HLGEM

回答

3

這是可能的查詢計劃是建立一個交叉連接,如WHERE子句中指定:

SELECT table_a.id AS table_a_id_1, 
     table_a2.id AS table_a_id_2 
FROM table_a join 
    table_b 
    on table_a.id = table_b.id LEFT JOIN 
    table_a AS table_a2 
    ON table_a.value = table_a2.value 
WHERE table_a.value_id = 112 AND 
     table_a2.value_id = 113 AND 
     table_a.status != table_a2.status 

這也表明,在table_a.id和table_a.value和table_b.id索引可能幫助很多。現在

,你也許可以簡化這個查詢了很多。例如,它似乎在table_a中獲得112,113對,其狀態不同。我真的不知道table_b在哪裏被使用,除非有一些過濾標準。你可以更有效地得到這個列表doiing類似的東西:

SELECT table_a.id AS table_a_id_1, 
     table_a2.id AS table_a_id_2 
FROM (select ta.* from table_a ta where ta.value_id = 112) ta join 
    (select ta.* from table_a ta where ta.value_id = 113) ta2 
    ON ta.value = ta2.value and 
     ta.status != ta2.status 
+0

table_a2.value_id = 113需要是在where子句中或要轉換左連接到內連接。而table_a.status!= table_a2.status需要合併以避免將空值與值進行比較。 – HLGEM

+0

我在這裏做一個連接,並將左連接轉換爲常規連接。我認爲左連接是多餘的,因爲原始查詢中的where子句確保table_a2端的NULL值被刪除。但是,我從來沒有真正想過左連接在「開」的條件不引用第一個表,所以我不是在這種情況下,知道什麼SQL指定(或MySQL做什麼)。也許它會在前兩個表上進行交叉連接,並且這個連接還會被連接到第三個表上? –