MYSQL加速查询

时间:2015-01-12 12:14:24

标签: mysql

美好的一天。 我的任务是尝试加速一些运行缓慢的查询,但作为一个MYSQL新手,我不确定我是否已经取得了最好的结果。我已经意识到论坛已经充斥着这些类型的问题,而且我已经阅读了很多这些问题,但如果可能的话,我还是会感激一些帮助。

我通过剥离连接开始优化过程,并首先尝试加速基本选择。该表中有大约4 400 000个条目,查询返回的区域为1 800 000个条目。

我从这开始:

select  
   ID,
   CallStarted,
   CallDirection 
from 
   TRMSMain.tblcalldata CALLDATA  
   where CallStarted BETWEEN '2014-02-10' AND '2014-05-11 23:59:59' 
ORDER BY ID DESC LIMIT 0 , 50;

花了大约360秒。 然而,这需要2秒钟:

select
  ID,
  CallStarted,
  CallDirection 
from 
  TRMSMain.tblcalldata CALLDATA  
where CallStarted BETWEEN '2014-02-10' AND '2014-05-11 23:59:59' 
LIMIT 0 , 50;

虽然最后一个查询返回了范围中的前50个,而不是最后的50个,但它让我相信“按顺序排序”操作非常昂贵。 然后我摆弄了一下并想出了以下内容(当然这不是完成它的唯一方法),这需要20到(有时)40秒:

use trmsmain;
RESET QUERY CACHE;
drop procedure if exists intTest;
delimiter #
create procedure intTest()
BEGIN
    declare lastID int unsigned default 0;
    declare frstID int unsigned default 0;
    select
        (select max(ID) from trmsmain.tblcalldata where  (CallStarted BETWEEN '2014-02-10' AND '2014-05-11 23:59:59'))
        into lastID;
    set     frstID = lastID - 49;
    CREATE TEMPORARY TABLE IF NOT EXISTS table2 (index (ID)) AS
    (       
        select
            ID,
            CallStarted,
            CallDirection
        from
            trmsmain.tblcalldata CALLDATA  
        where
            ID between frstID AND lastID
    );
    select * from table2 order by ID desc;
END #
delimiter ;
call intTest();

结果正是我所需要的,并且callstarted是一个索引字段,但我的问题是这种性能是否可以接受(我能期待的最好)。我的电脑是中档,有4GB的Ram。

请指教。 谢谢。

更多信息:

我的SQL脚本等同于:

select
    ID,
    CallStarted,
    CallDirection
  from trmsmain.tblcalldata CALLDATA  

where  ID between (select(select max(ID) from trmsmain.tblcalldata  where  (CallStarted BETWEEN '2014-02-10' AND '2014-05-11 23:59:59'))  - 49) AND 
(select max(ID) from trmsmain.tblcalldata   where  (CallStarted BETWEEN '2014-02-10' AND '2014-05-11 23:59:59'));

我只是这样做,因为我想看看上面是否会重复使用MAX的结果,所以我将上面的结果与脚本的结果进行了比较(类似)。

在我看了他解释之后,我很困惑并删除了所有索引,除了callstarted上的索引。 ID是主键。

只有一个索引将时间缩短到一秒。即使使用“强制索引(callstarted)”,我也无法接近这个结果。

我现在更加困惑了。

此致

3 个答案:

答案 0 :(得分:0)

如果你知道顺序分配了id,你可以试试这个:

select ID, CallStarted, CallDirection 
from TRMSMain.tblcalldata CALLDATA  cd JOIN
     (select MIN(id) as minid, MAX(id) as maxid
      from TRMSMain.tblcalldata CALLDATA cd2
      where CallStarted BETWEEN '2014-02-10' AND '2014-05-11 23:59:59'
     ) s
     on cd.id >= minid and cd.id <= maxid
order by id desc
limit 0, 50;

如果MySQL足够聪明,可以同时使用onorder by的索引,那么性能可能比你的版本更快。

尝试在TRMSMain.tblcalldata(CallsStarted)上创建索引。

答案 1 :(得分:0)

如果您要根据您的日期/时间查找最新信息,并根据您的反馈,在呼叫结束时插入呼叫,从而根据呼叫的结束时间顺序进行呼叫。数据样本:

ID   CallStarted          CallEnded
1    2015-01-12  8:37     2015-01-12  8:44
2    2015-01-12  8:42     2015-01-12  8:52
3    2015-01-12  8:29     2015-01-12  9:09
4    2015-01-12  8:56     2015-01-12  9:11
5    2015-01-12  8:30     2015-01-12  9:12
6    2015-01-12  9:09     2015-01-12  9:32

如果是这种情况,根据何时调用ENDED而不是启动来进行查询更有意义?唯一一次出现问题的是那些明确在午夜到第二天滚动的电话。

我仍然会有一个包含您感兴趣的元素的COVERING INDEX,因此它不必返回到原始数据页面,但可以直接从索引中获取它们。在这种情况下,移动调用END Date进入主要位置的指数:

在(CallEnded,CallStarted,ID,CallDirection)上构建索引

然后尝试

select
      C.ID,
      C.CallStarted,
      C.CallDirection 
   from 
      TRMSMain.tblcalldata C  
   where 
      C.CallEnded BETWEEN '2014-02-10' AND '2014-05-11 23:59:59'
   order by
      C.CallEnded DESC
   LIMIT 
      0, 50

这对你有用吗......

答案 2 :(得分:0)

感谢所有花时间查看我的问题的人,我总是对计算社区的支持和帮助感到惊讶。看起来我的问题是没有使用正确的索引,而且替换“ORDER BY DESC”的解决方法也削减了很多时间。我将尝试使用我在此处发现的内容来改进我的代码。保持健康。