美好的一天。 我的任务是尝试加速一些运行缓慢的查询,但作为一个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)”,我也无法接近这个结果。
我现在更加困惑了。
此致
答案 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足够聪明,可以同时使用on
和order 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”的解决方法也削减了很多时间。我将尝试使用我在此处发现的内容来改进我的代码。保持健康。