美好的一天。 我的任务是尝试加快一些运行缓慢的查询,但作为 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 个,这让我相信“order by desc”操作非常昂贵。 然后我摆弄了一下并想出了以下方法(当然这不是唯一的方法),这需要 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 是一个索引字段,但我的问题是这种性能是否可以接受(我能期望的最好)。我的 PC 是中档,有 4GB 内存。
请指教。 谢谢。
更多信息:
我的 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为主键。
只有一个索引可以将时间缩短到一秒。即使使用“force index(callstarted),我也无法接近这个结果。
不知何故,我现在更加困惑了。
问候
最佳答案
如果您知道 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)
上创建索引。
关于MYSQL 加速查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27901783/