count優化
MyISAM會將總記錄數緩存,但如果加上where條件,則緩存值失效。
若有500w條記錄,需要統計id > 100的總行數。
一個優化思路,反向操作,降低查詢次數。
select
(select count(*) from student) - count(*)
from student where id <= 100;
優化Limit分頁(深分頁問題)
場景模擬
插入10w條樣例數據
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`stuid` int(11) unsigned NOT NULL AUTO_INCREMENT,
`stuname` varchar(200) DEFAULT NULL,
`stuaddress` varchar(200) DEFAULT NULL,
`classid` int(11) DEFAULT NULL,
PRIMARY KEY (`stuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DELIMITER //
create procedure doinsert1()
begin
declare i int;
declare j int;
set i = 1;
set j = 1;
while i<100000 do
insert into student(stuid,stuname,stuaddress,classid)values(i,concat(i,'張',j),'深圳',i+j);
set i = i+1;
set j = j+1;
end while;
end;//
call doinsert1()
執行小的偏移量查詢
執行大的偏移量查詢
分析
# 打開show profile,收集在執行語句的時候所使用的資源。
SET profiling = 1;
# show profiles;
show profiles;
# 通過對應的QUERY_ID查看
show profile for query 1;
耗時最多的是Sending Data,可以看到查詢數據花了大量的時間。
優化方案一
將limit轉換為where...between
select * from student where stuid between 90002 and 90021;
優化方案二
通過where縮小范圍
如上一頁獲取到的最后的結果是90001,則下一頁則加上classid > 90001,來縮小范圍。
select * from student where classid > 90001 order by stuid limit 20;
優化方案三
從業務上進行優化,結合業務,將最大翻頁控制在指定范圍,例如最多只允許翻到100頁。
若想要獲得更多數據,需要修改關鍵詞或增加篩選條件。
優化方案四
利用覆蓋索引,先查詢指定的id,然后用inner join進行關聯。
select s.* from student s inner join (
select stuid from student order by classid limit 90000,20) as tmp on s.stuid = tmp.stuid;
使用變量減少查詢次數
需求是:使用分數排名,存在並列第一或第n的情況。
create table t10( name char(10) not null default '', score int not null default 0)engine myisam charset utf8;
insert into t10 values('zhang',100),('wang',95),('li',92),('liu',100);
使用變量set @age:=20
,查詢變量select @age
select name,(@curr:=score) as score,@rank:=if(@curr<>@prev,@rank:=@rank+1,@rank) as rank,@prev:=score as prev from t10 order by score desc;