2013-01-09 104 views
0

與使用左連接的非常慢的mysql查詢有問題。mysql左連接語句運行緩慢

SELECT ip,T1.ipaddr,host,referrer,agent,page,url,thedate,DV,PV,notes 
FROM visits_temp AS T1 
LEFT JOIN (
    SELECT ipaddr,COUNT(DISTINCT LEFT(thedate,10)) AS DV 
    FROM visits GROUP BY ipaddr 
) AS T2 ON T1.ipaddr = T2.ipaddr 
LEFT JOIN (
    SELECT ipaddr,notes 
    FROM topvisitors 
) As T3 ON T3.ipaddr = T1.ipaddr 
LEFT JOIN (
    SELECT ipaddr,COUNT(ip) AS PV 
    FROM visits 
    GROUP BY ipaddr 
) AS T4 ON T4.ipaddr = T1.ipaddr 
WHERE referrer = '' AND 
    thedate BETWEEN '2013-01-07 00:00:00' AND '2013-01-09 23:59:59' 
GROUP BY T1.ip 
ORDER BY thedate desc 

的這裏的目標是讓所有的直接訪問者流量比左側JOINS做一個查找給天的訪問總數(DV)和頁面瀏覽的總數(PV)的網站。訪問表目前有大約290萬條記錄,並且ipaddr和日期字段被索引。此查詢需要接近90秒才能完成。

SELECT ipaddr,COUNT(DISTINCT LEFT(thedate,10)) AS DV FROM visits GROUP BY ipaddr 

SELECT ipaddr,COUNT(ip) AS PV FROM visits GROUP BY ipaddr 

個人在左側選擇語句加入時,自己會跑0.03秒內完成。也許在這種情況下,LEFT JOIN並不是正確的選擇,我願意接受替代品。

+1

您是否試過'EXPLAIN PLAN'?它顯示了什麼? –

+0

在日期範圍內使用'between'時,我已經有很大的表執行了非常糟糕的事情。不知何故,當這樣的構造被使用時,mysql拒絕索引。 –

+0

@MarcB是否使用'Date> = LowerBownd和Date <= UpperBound'解決了這個問題? –

回答

0

您在where子句中使用referrer和thedate。在visits_temp表中的這兩個字段上創建複合索引可能會提高性能。

確保您在topvisitors表中的ipaddr字段上也有一個索引。

0

這4個子查詢可能會減慢一點。

這應該是相同的查詢,只是速度更快:

SELECT ip,T1.ipaddr,host,referrer,agent,page,url,thedate,DV,PV,notes 
FROM visits_temp AS T1 
LEFT JOIN (
    SELECT ipaddr, COUNT(DISTINCT LEFT(thedate,10)) AS DV, COUNT(ip) AS PV 
    FROM visits 
    GROUP BY ipaddr 
) AS T2 ON T1.ipaddr = T2.ipaddr 
LEFT JOIN topvisitors T3 ON T3.ipaddr = T1.ipaddr 
WHERE referrer = '' AND 
    thedate BETWEEN '2013-01-07 00:00:00' AND '2013-01-09 23:59:59' 
GROUP BY T1.ip 
ORDER BY thedate desc 

如果T1每一行保證有一個匹配的行T2T3,您可以取代你LEFT JOINJOIN,這應該允許優化器做更多的事情,這也可以加快速度(雖然有例外)。

我無法想象這會返回所需的結果,它將分組在ipaddr上,但只返回(任意)1個這些分組,每個ip。 MySQL不會阻止這一點。如果你詳述一下你的需求(根據你使用的字段/表格),解決這個問題不應該太困難(儘管這在技術上可能屬於不同的問題)。