使用左连接有一个非常慢的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
这里的目标是获得网站的所有直接访问者流量,而不是LEFT JOINS进行查找以给出访问天数(DV)和浏览页面总数(PV)。访问表当前有大约290万条记录,并且ipaddr和thedate字段已编入索引。此查询需要近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
LEFT JOINS中的各个select语句在自行运行时将在0.03秒内完成。也许LEFT JOIN不是在这种情况下正确的方式我会接受替代方案。
答案 0 :(得分:0)
您在where子句中使用referrer和thedate。在visits_temp表中的这两个字段上创建复合索引可以提高性能。
确保topvisitors表中的ipaddr字段也有索引。
答案 1 :(得分: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
的每一行都保证在T2
和T3
中有匹配的行,则可以将LEFT JOIN
替换为JOIN
,这应该是允许优化器做更多,这也可以加快速度(虽然有例外)。
我无法想象这会返回所需的结果,它会在ipaddr
上分组,但只会为每个ip
返回(任意)1个这样的分组。 MySQL并没有阻止这种情况。如果你详细说明你的要求(就你使用的字段/表格而言),解决这个问题应该不会太难(尽管这可能在技术上属于另一个问题)。