2013-07-29 149 views
0

我試圖在我的網站上獲得一組商家的訂單金額。我必須檢查兩個項目類型,這使查詢非常緩慢。這是我現在使用嵌套連接的優化

SELECT User.ID, COUNT(Order.ID) FROM User 
    INNER JOIN UserGroup ON UserGroup.userID = User.ID AND UserGroup.groupID = 4 
    LEFT JOIN Meal ON Meal.userID = User.ID 
    LEFT JOIN Produce ON Produce.userID = User.ID 
    LEFT JOIN Order ON (type = 'Meal' AND typeID = Meal.ID) OR (type = 'Produce' AND typeID = Produce.ID) 
WHERE Order.rating > 50 AND Order.status = 'DELIVERED' 
ORDER BY User.ID ORDER BY COUNT(Order.ID) DESC 

當然,所有的連接和狀態列索引(transscribed的可讀性)查詢。當我運行查詢的EXPLAIN時,我可以看到它作爲type ALL加入了Order tabel,我很確定這是問題所在,我無法弄清楚如何使它作爲ref加入。它目前需要2.74秒才能執行。

(不檢查在此查詢錯別字,我改表名和字段名的可讀性,並有可能錯過了一些東西,關於我的問題但是所有的信息都在)。

輸出的 EXPLAIN

+----+-------------+-----------+--------+-------------------------+---------+---------+------------------+------+---------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-----------+--------+-------------------------+---------+---------+------------------+------+---------------------------------+ | 1 | SIMPLE | UserGroup | ref | userID,groupID | groupID | 4 | const | 74 | Using temporary; Using filesort | | 1 | SIMPLE | User | eq_ref | PRIMARY,isDeleted | PRIMARY | 4 | UserGroup.userID | 1 | Using where | | 1 | SIMPLE | Meal | ref | userID,isDeleted,status | userID | 4 | UserGroup.userID | 18 | | | 1 | SIMPLE | Produce | ref | userID,status,isDeleted | userID | 4 | User.ID | 13 | | | 1 | SIMPLE | Order | ALL | status,isDeleted,type | NULL | NULL | NULL | 1960 | | +----+-------------+-----------+--------+-------------------------+---------+---------+------------------+------+---------------------------------+ 
+1

您能否將'EXPLAIN'的輸出與'Order'表上的索引一起發佈? – kastermester

+1

通常,聯合ALl查詢比具有或加入條件的查詢更快。我知道這對於SQL Server來說是正確的,我懷疑我的sqlas也是如此。 OR條件應避免不惜一切代價。 – HLGEM

+0

**您需要向我們展示表格和索引定義**以及每個表格的行數。也許你的表格定義不好。也許索引沒有正確創建。也許你沒有一個你認爲你做過的那個專欄的索引。沒有看到表和索引定義,我們不能說。我們還需要行計數,因爲這會大大影響查詢優化。如果你知道如何做一個'EXPLAIN'或者得到一個執行計劃,那就把結果也放在問題中。 –

回答

0

我解決了這個問題。我可以去兩種方式:

使用UNION在上面的意見提出(執行時間:〜10.5ms)

SELECT User.ID, SUM(orderCount) AS totalOrders FROM (
    (
    SELECT User.ID, COUNT(Order.ID) AS orderCount 
    FROM User 
    INNER JOIN UserGroup ON User.ID = UserGroup.userID AND UserGroup.groupID = 4 
    LEFT JOIN Meal ON User.ID = Meal.userID 
    LEFT JOIN Order ON Order.type = 'Meal' AND Order.typeID = Meal.ID 
    GROUP BY User.ID 
) 
    UNION ALL 
    (
    SELECT User.ID, COUNT(Order.ID) AS orderCount 
    FROM User 
    INNER JOIN UserGroup ON User.ID = UserGroup.userID AND UserGroup.groupID = 4 
    LEFT JOIN Produce ON User.ID = Produce.userID 
    LEFT JOIN Order ON Order.type = 'Produce' AND Order.typeID = Produce.ID 
    GROUP BY User.ID 
) 
) AS uni 
GROUP BY User.ID 
ORDER BY totalOrders DESC 

或者,我可以讓Order表主表,並做了GROUP BY COALESCE()(執行時間:約76毫秒)

SELECT COALESCE(Meal.userID,Produce.userID) AS cook, COUNT(Order.ID) AS totalOrders 
FROM Order 
LEFT JOIN Meal ON Order.type = 'Meal' AND Order.typeID = Meal.ID 
LEFT JOIN Produce ON Order.type = 'Produce' AND Order.typeID = Produce.ID 
INNER JOIN UserGroup ON UserGroup.groupID = 4 AND (Meal.userID = UserGroup.userID OR Produce.userID = UserGroup.userID) 
GROUP BY cook 
HAVING cook IS NOT NULL 
ORDER BY TotalOrders DESC 

我決定在後者的可讀性。如果有人知道如何在原始問題中解決我的問題,請告訴我。我將它作爲一個更大腳本的一部分編寫,我可以快速加入查詢修飾符。如果我必須改變這個查詢,這些不再有效。