2011-06-28 253 views
0

我非常需要幫助,在高流量網站上,過去6個月中一直引起很多悲痛的查詢。我是一名能夠編寫簡單SQL查詢的前端開發人員,因此我無法自行解決此問題。該查詢現在經常因缺少內存或CPU或VPS上其他查詢的干擾而鎖定mysql數據庫。我升級了硬件,但單靠這一點無法解決問題。因此,以下是對查詢嘗試執行的操作的描述:需要幫助來優化SQL查詢

用戶訪問特定URL(例如the_source_url)。應用程序試圖獲取其他用戶(他們也訪問過the_source_url)早些時候訪問過的相關source_urls,按最頻繁訪問次數最少訪問次數排序。基本上,應用程序試圖找到具有類似興趣的用戶並顯示他們以前訪問的其他頁面。

這是「複雜的查詢」,我寫我年輕的時候/愚蠢的網站沒有流量:

SELECT DISTINCT(SOURCE_URL), COUNT(SOURCE_URL) CATCOUNT 
    FROM topsources 
WHERE SOURCE_URL <> ? 
    AND USER_ID IN (SELECT DISTINCT(USER_ID) 
        FROM topsources WHERE SOURCE_URL = ?) 
GROUP BY SOURCE_URL ORDER BY CATCOUNT DESC 

這是表結構:

`topsources` (
    `USER_ID` varchar(255) NOT NULL, 
    `DATE_AND_HOUR` varchar(255) NOT NULL, 
    `UPDATED_TIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    `ITEM_ID` int(11) NOT NULL, 
    `SOURCE_URL` varchar(100) NOT NULL, 
    `FEED_PAGE_URL` varchar(255) NOT NULL, 
    `CATEGORY_URL` varchar(100) NOT NULL, 
    `REFERRER` varchar(2048) DEFAULT NULL, 
    PRIMARY KEY (`USER_ID`,`DATE_AND_HOUR`(30),`ITEM_ID`), 
    KEY `USER_ID` (`USER_ID`), 
    KEY `FEED_PAGE_URL` (`FEED_PAGE_URL`), 
    KEY `SOURCE_URL` (`SOURCE_URL`), 
    KEY `CATEGORY_URL` (`CATEGORY_URL`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8; 

請注意,我已經嘗試了內部連接而不是子選擇,但這不起作用。即,下面的查詢不返回與上述查詢相同的結果。

​​3210
+0

當您使用GROUP BY時,不要使用DISTINCT。 – niktrs

回答

4

IN subselects沒有在MySQL中優化。而不是執行子選擇,然後選擇outser,MySQL爲外部選擇匹配的每一行執行子選擇。因此,IN子句中的子查詢應該用連接替換。以下是查詢的更快版本:

SELECT DISTINCT(SOURCE_URL), COUNT(SOURCE_URL) CATCOUNT 
FROM topsources 
INNER JOIN 
(SELECT DISTINCT(USER_ID) 
       FROM topsources WHERE SOURCE_URL = ?) as t 
ON (topsources.USER_ID = t.USER_ID) 
WHERE SOURCE_URL <> ? 
GROUP BY SOURCE_URL ORDER BY CATCOUNT DESC 
+1

上面的代碼是MySQL如何解釋原始查詢或建議改進的示例嗎? –

+0

仔細閱讀:由於MySQL處理子查詢的方式(如上所述),IN子句中的子查詢必須替換爲連接。因此重寫的查詢是一個建議的改進 –

+0

對不起,我不是無禮的意思。我不確定你最初想傳達什麼。感謝您清理它。 –

1

這是要求正常化的要求。你真正需要的是一個鏈接表像

id | url 
1 | http://.... 

然後在你的topsources表

id | url_id 
1 | 1 

然後你DISTINCT(url_id)應顯著更快。