2016-11-19 51 views
0

我遇到以下查詢問題。它從數據庫表中選擇日誌記錄。MySQL查詢非常慢(20到60秒!) - 爲什麼?

SELECT paymentslog.*, user.username, user.usergroupid, user.displaygroupid, 
     purchase_temp.threadid 
    FROM " . TABLE_PREFIX . "paymentslog AS paymentslog 
    LEFT JOIN " . TABLE_PREFIX . "user AS user 
     ON (paymentslog.userid = user.userid) 
    LEFT JOIN " . TABLE_PREFIX . "paymenttransaction AS paymenttransaction 
     ON (paymentslog.transactionid = paymenttransaction.transactionid) 
    LEFT JOIN " . TABLE_PREFIX . "paymentinfo AS paymentinfo 
     ON (paymenttransaction.paymentinfoid = paymentinfo.paymentinfoid) 
    LEFT JOIN " . TABLE_PREFIX . "purchase_temp AS purchase_temp 
     ON (paymentinfo.hash = purchase_temp.hash) $filterlogs_where 
    GROUP BY paymentslog.logid 
    ORDER BY paymentslog.dateline DESC 
    LIMIT $startat, $perpage 
  • 所有這些連接都需要對SELECT訪問線程ID除了與用戶表的連接來訪問用戶名,usergroupid和displaygroupid
  • 它需要20秒運行(!),我嘗試在解決這個問題,在爲列transactionid(表paymentlog)添加INDEX之後,現在需要...... 60秒!
  • 出於某種原因,這是多次返回特定行,基於這個原因,我固定它通過添加一個「GROUP BY paymentslog.logid」

我必須注意的是:
- $ filterlogs_where PHP變量具有查詢的WHERE(我通過php爲付款日誌創建了不同的過濾器)。 默認情況下,$ filterlogs_where的值爲「1 = 1」,如果我必須應用過濾器,則添加。=「AND paymentslog.userid = X」等。

任何想法爲什麼此查詢是如此之慢?
我想我已經看過並且寫了幾秒或幾毫秒內運行的更復雜的查詢。爲什麼這個問題與上面的查詢?

+0

儘管加入哈希是可能的,但加入整數應該快很多。我們在談論多少數據,你忽略了告訴我們。 – Xorifelse

+5

加入整數可能會更快一些,但就是這樣。如果沒有所有相關表的CREATE TABLE語句和針對上述查詢的EXPLAIN,不可能幫助解決這個問題 – Strawberry

+0

@Xorifelse - 沒有'HASH'索引。無論如何,哈希只比BTree略快。 –

回答

0

首先,我必須告誡你不要有多個具有相同模式的表。這通常是一個糟糕的設計。

你真的需要LEFT?也就是說,即使「右」表沒有任何內容,您還是希望返回一行?如果沒有,只需使用JOIN

擺脫LEFTs可能會擺脫GROUP BY。加入後跟GROUP BY通常會導致「膨脹行數」,然後是「通過組縮小」。這會在此過程中創建一個巨大的臨時表,從而減慢速度。

然後我需要指出Pagination via Offset有問題 - 通常會導致查詢時間過長。但是,我們需要擺脫GROUP BY以使此技術成爲可能。

請使用較短的別名。

現在,回到您的具體情況......那麼,首先工作在上面的東西。並供應SHOW CREATE TABLE。然後像這樣的事情會加快速度:

SELECT ... 
    FROM (SELECT id 
       ORDER BY dateline DESC 
       LIMIT $startat, $perpage) AS pl 
    JOIN user ON ... 
    JOIN ... 
    ORDER BY dateline DESC; -- yes, needs repeating 
+0

你好瑞奇,非常感謝你的分析回覆!正如我可以理解你的例子,我寫了以下查詢:http://pastebin.com/GQAWe9AZ這是正確的嗎?它似乎有很多記錄返回正確的結果,但與2記錄的測試,沒有人出現。對不起,長的別名,將盡快修復它們。 – user3594130

+0

也許你確實需要'LEFT'。 (我不明白查詢的_intent_。) –

+0

好的!查詢工作完美,非常感謝你:) – user3594130