任何人都知道如何优化此查询?它工作正常,但是当负载很重时它会导致服务器超时。
$screenRestrict="clientID='1' AND screenID='1'";
$lastupdate="1318515710";
INSERT INTO allvisits (clientID, screenID, hitID, entryPageID, entryPageName, xentryTime, xexitTime, pagecount, minsonsite)(
SELECT
clientID, screenID, id AS hitID, pageID AS entryPageID,
(SELECT name FROM pages WHERE id=entryPageID) AS entryPageName,
(SELECT clicktime FROM clicks WHERE id = hitID AND isFirstClick=1 ) AS xentryTime,
(SELECT MIN(clicktime) FROM clicks WHERE $screenRestrict AND isLastClick=1 AND clicktime > xentryTime) AS xexitTime,
(SELECT COUNT(*) FROM clicks WHERE $screenRestrict AND clicktime BETWEEN xentryTime AND xexitTime) AS pagecount,
(SELECT (xexitTime-xentryTime)/60) AS minsonsite
FROM clicks WHERE $screenRestrict AND isFirstClick=1 AND clicktime>'$lastupdate'
)
非常感谢:)
更新
感谢所有提示。我已经为isLastClick添加了一个索引,并设法加快它的速度,但是在低服务器负载下仍需要+10秒。我已经确定了最后一个瓶颈并在下面标出了它。有没有更好的方法来选择晚于xentrytime的第一个“isLastClick”记录?
SELECT clientid,
screenid,
id AS hitid,
pageid AS entrypageid,
clicktime AS xentrytime,
(SELECT name
FROM pages
WHERE id = entrypageid) AS entrypagename,
(SELECT clicktime
FROM clicks
WHERE clicktime > xentrytime //<<removing this cuts 8.5 seconds!!
AND screenid = '2'
AND islastclick = 1
LIMIT 1) AS xexittime,
(SELECT COUNT(1)
FROM clicks
WHERE screenid = '2'
AND clicktime BETWEEN xentrytime AND xexittime) AS pagecount,
(SELECT ( xexittime - xentrytime ) / 60) AS minsonsite
FROM clicks
WHERE screenid = '2'
AND isfirstclick = 1
AND clicktime > '1318961057'
答案 0 :(得分:1)
请检查评论。
如果页面的$ screenrestrict和页面ID相同。尝试使用该页面标识
加入内部表我不确定您对xentrytime和xexittime列的想法。因为,我看到使用子查询获取相同的东西。
请记住,要调优查询,请尝试获取过滤器并限制每个子查询中选择的行数。有些过滤器是基于业务逻辑编写的,因此在编写查询时也要考虑包含这些条件,并查看解释计划中的性能是否有所提高。
INSERT INTO allvisits
(clientid,
screenid,
hitid,
entrypageid,
entrypagename,
xentrytime,
xexittime,
pagecount,
minsonsite)
(SELECT clientid,
screenid,
id AS hitid,
pageid AS entrypageid,
(SELECT name
FROM pages
WHERE id = entrypageid) AS entrypagename
,
clicktime AS xentrytime, //this should work w.r.t your code
(SELECT MIN(clicktime) //try to change this logic. The logic written here doesnt look good at all. and try to filter out data by joining with outer table.
FROM clicks
WHERE $screenrestrict
AND islastclick = 1
AND clicktime > xentrytime) AS xexittime,
(SELECT COUNT(1) //this will give some performance improvement
FROM clicks
WHERE $screenrestrict
AND clicktime BETWEEN xentrytime AND xexittime) AS pagecount,
(SELECT ( xexittime - xentrytime ) / 60) AS minsonsite
FROM clicks
WHERE $screenrestrict
AND isfirstclick = 1
AND clicktime > '$lastupdate')
<强>更新强>
这两个内部查询需要更多的微调
SELECT MIN(innClick.clicktime)
FROM clicks innClick1
WHERE innClick1.screenid = '2' // when u put it as part of big query use WHERE innClick1.screenid = outClick.screenid instead of hard coding it. where outClick is alias for Click table in outside
AND innClick1.islastclick = 1
AND innClick1.clicktime > innClick1.xentrytime
SELECT COUNT(1)
FROM clicks innClick2
WHERE innClick2.screenid = '2'
AND innClick2.clicktime BETWEEN innClick2.xentrytime AND innClick2.xexittime
w.r.t解释计划
单击时间,xentrytime和xexittime,如果已建立索引,我认为查询的性能会更好。您可以尝试but still indexing will slow your insert statements
,因为每次插入时都应更新这些额外的索引。