Select / order by desc / 限制查询速度
Select / order by desc / limit query speed
我发现这两个查询的速度差异很大;第一个在 0.3 秒内运行,第二个在 76 秒内运行。
第一个查询仅 select 键,而第二个查询 select 一个附加字段,它是一个 int(11)。我可以将第二个字段替换为任何其他字段,结果相同。出于某种原因,仅选择密钥要快得多?
谁能解释速度上的巨大差异?我被这个难住了。
Q1:
SELECT ID
FROM TRMSMain.tblcalldata
WHERE (
CallStarted BETWEEN '2014/06/13' AND '2014/06/13 23:59:59')
ORDER BY ID DESC LIMIT 0 , 50
Q2:
SELECT ID, Chanid
FROMTRM SMain.tblcalldata
WHERE (
CallStarted BETWEEN '2014/06/13' AND '2014/06/13 23:59:59')
ORDER BY ID DESC LIMIT 0 , 50
此致
我想你的 CallStarted
列有一个索引,ID
是主键。您的第一个查询可以对该索引进行所谓的范围扫描,并快速检索行标识,因为 InnoDB 上的二级索引也包括主键。
所以它最终只做了一点点工作。
您的第二个查询必须从主 table 中获取数据。特别是它必须获取 ChanID
变量。然后它必须对整个混乱进行排序,从末尾抓取 50 个值,并丢弃其余的排序。
执行延迟连接以获取额外的列。也就是说,只需对 ID 号进行排序,然后从 table 中获取您需要的其余数据。这样你只需要获取 50 行的数据。
像这样:
SELECT a.ID, a.Chanid, a.WhatEver, a.WhatElse
FROM TRMSMain.tblcalldata a
JOIN (
SELECT ID
FROM TRMSMain.tblcalldata
WHERE CallStarted BETWEEN '2014/06/13' AND '2014/06/13 23:59:59'
ORDER BY ID DESC
LIMIT 0, 50
) b ON a.ID = b.ID
ORDER BY a.ID DESC
你知道内部查询很快;你已经证明了这一点。 JOIN
只是利用这种速度(基于对索引的良好使用)来获取所需行的详细数据。
专业提示:避免 BETWEEN
用于 date/time 范围,因为如您所知,它无法很好地处理范围的末尾。这将同样有效并避免 59:59
废话。
WHERE CallStarted >= '2014/06/13'
AND CallStarted < '2014/06/13' + INTERVAL 1 DAY
它从 6 月 13 日午夜开始抓取记录,并在第二天的午夜(<
)之前获取所有记录,但不包括(<
)。
我发现这两个查询的速度差异很大;第一个在 0.3 秒内运行,第二个在 76 秒内运行。
第一个查询仅 select 键,而第二个查询 select 一个附加字段,它是一个 int(11)。我可以将第二个字段替换为任何其他字段,结果相同。出于某种原因,仅选择密钥要快得多? 谁能解释速度上的巨大差异?我被这个难住了。
Q1:
SELECT ID
FROM TRMSMain.tblcalldata
WHERE (
CallStarted BETWEEN '2014/06/13' AND '2014/06/13 23:59:59')
ORDER BY ID DESC LIMIT 0 , 50
Q2:
SELECT ID, Chanid
FROMTRM SMain.tblcalldata
WHERE (
CallStarted BETWEEN '2014/06/13' AND '2014/06/13 23:59:59')
ORDER BY ID DESC LIMIT 0 , 50
此致
我想你的 CallStarted
列有一个索引,ID
是主键。您的第一个查询可以对该索引进行所谓的范围扫描,并快速检索行标识,因为 InnoDB 上的二级索引也包括主键。
所以它最终只做了一点点工作。
您的第二个查询必须从主 table 中获取数据。特别是它必须获取 ChanID
变量。然后它必须对整个混乱进行排序,从末尾抓取 50 个值,并丢弃其余的排序。
执行延迟连接以获取额外的列。也就是说,只需对 ID 号进行排序,然后从 table 中获取您需要的其余数据。这样你只需要获取 50 行的数据。
像这样:
SELECT a.ID, a.Chanid, a.WhatEver, a.WhatElse
FROM TRMSMain.tblcalldata a
JOIN (
SELECT ID
FROM TRMSMain.tblcalldata
WHERE CallStarted BETWEEN '2014/06/13' AND '2014/06/13 23:59:59'
ORDER BY ID DESC
LIMIT 0, 50
) b ON a.ID = b.ID
ORDER BY a.ID DESC
你知道内部查询很快;你已经证明了这一点。 JOIN
只是利用这种速度(基于对索引的良好使用)来获取所需行的详细数据。
专业提示:避免 BETWEEN
用于 date/time 范围,因为如您所知,它无法很好地处理范围的末尾。这将同样有效并避免 59:59
废话。
WHERE CallStarted >= '2014/06/13'
AND CallStarted < '2014/06/13' + INTERVAL 1 DAY
它从 6 月 13 日午夜开始抓取记录,并在第二天的午夜(<
)之前获取所有记录,但不包括(<
)。