通过desc / limit查询速度选择/排序

时间:2015-02-16 12:51:36

标签: mysql database-performance

我发现这两个查询之间的速度差异很大;第一个在0.3秒内运行,第二个在76秒内运行。

第一个查询仅选择键,而第二个查询选择另一个字段,即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

此致

1 个答案:

答案 0 :(得分:2)

我认为您的CallStarted列上有索引,而ID是主键。您的第一个查询可以对该索引执行所谓的范围扫描,并快速检索行标识,因为InnoDB上的二级索引还包括主键。

所以它最终只做了一点工作。

您的第二个查询必须从主表中获取数据。特别是它必须获取ChanID变量。然后它必须对整个混乱进行排序,从最后获取50个值,并丢弃其余的那些。

执行延迟联接以获取额外的列。也就是说,只需对ID号进行排序,然后从表中获取所需的其余数据。这样你只需要抓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日期/时间范围,因为您知道它处理范围的结束很差。这也会表现良好并避免59:59废话。

 WHERE CallStarted >= '2014/06/13' 
   AND CallStarted <  '2014/06/13' + INTERVAL 1 DAY

它从6月13日的午夜开始抓取记录,并在第二天的午夜时间内完成但不包括(<)。