2011-12-25 79 views
6

下面的查詢是相對緩慢(0.7秒〜6K行)MySQL的慢組通過/以便通過

SELECT items.*, COUNT(transactions.ID) 
    FROM items 
    INNER JOIN users ON (items.USER = users.ID) 
    LEFT JOIN transactions ON (items.id = transactions.item) 
    WHERE items.ACTIVE = 1 
    AND items.DELETED_AT IS NULL 
    GROUP BY items.ID 
    ORDER BY items.DATE DESC 
    LIMIT 20 

但是,當通過items.ID DESC代替items.DATE有序顯着加快。事務連接到一個大表(〜250k行)並且是一對多的。日期列有一個索引。

有什麼辦法一般地改善ORDER BY的性能嗎?

編輯:對items.user,transactions.item和items.date的索引。項目有49列,用戶76和交易17.

+3

你可以提供模式,特別是三個表的索引? – TetonSig 2011-12-25 20:56:43

+0

我能想到的唯一事情是首先選擇由WHERE子句篩選並按子查詢日期排序的項目(或者在視圖中,如果MySQL不支持子查詢中的ORDER BY),然後在封閉查詢中執行你的加入。 (我不會寫這個作爲答案,因爲SO不鼓勵推測性答案。) – 2011-12-25 20:57:49

+0

你有沒有嘗試在'GROUP BY'中包含'items.DATE'(在第一個位置)? – 2011-12-25 23:16:15

回答

5

索引可以影響ORDER BY子句的性能。這MySQL manual page可能是值得你的時間。實質上,如果您通過作爲MySQL用於查詢的索引的一部分的列進行排序,則MySQL可以使用索引進行排序而不是數據本身。

在您的特定查詢中,DATE列具有索引這一事實並不重要,因爲該索引可能未在您的查詢中使用。您的WHERE聲明包含items.ACTIVEitems.DELETED_AT,並且如果這些列的索引被用於WHERE(不包括DATE列),則MySQL無法使用該索引按DATE排序,並且可能會訴諸文件分類。

如果你能想出一個可以被WHEREORDER BY使用的索引,那麼你會得到一個優化提升。在這種情況下,items.ACTIVE看起來像一個低基數列,所以假設items.DELETED_AT是一個日期,我可能會嘗試索引,如INDEX(DELETED_AT,DATE)該表。

使用EXPLAIN SELECT...也可以查看更多關於發生的事情,您可能會獲得一些進一步的見解。

0

這些東西,可以(讀不能保證)的幫助。

  1. 消除*項目。*並單獨列出每個字段。 49 列是不是你真的需要他們所有?
  2. 通常,引擎會優化查詢,以便在連接上考慮限制條件 。也許 引擎使用的計劃沒有這樣做(需要解釋計劃結果知道),所以 重新安排where子句和加入可能(不可能) 迫使引擎考慮這一點。 (見下文)
  3. 重建表的統計數據,如果許多更新,插入,刪除具有 發生隨着時間的推移,它可能表的統計信息是關閉和 必須 rebuilt 爲每個表

SELECT items.[list fields], COUNT(transactions.ID) 
    FROM items 
    INNER JOIN users ON (items.USER = users.ID) 
     AND items.Active=1 
     AND items.DELETED_AT is Null 
    LEFT JOIN transactions ON (items.id = transactions.item) 
    GROUP BY items.ID 
    ORDER BY items.DATE DESC 
    LIMIT 20 
2

SELECT * FROM(SELECT * FROM WHERE 1 GROUP BY ID限0,10 wp_users)爲X ORDER BY ID DESC

上面的查詢運行完美,我有一個很長的數據庫,用它。它通過我們從內部選擇查詢獲得的10個OR(xx)項目的列表進行排序,所以它非常快!