1.優(yōu)化特定類型的查詢
1.1優(yōu)化count()查詢
count(),是一個(gè)特殊的函數(shù),它可以統(tǒng)計(jì)列值得數(shù)量,也可以統(tǒng)計(jì)行數(shù)。在統(tǒng)計(jì)列值時(shí)要求列值不能為null。
當(dāng)我們想要統(tǒng)計(jì)結(jié)果集的行數(shù)的時(shí)候直接使用count(*),語(yǔ)義清晰,性能也更好。
在MyISAM引擎中在沒(méi)有任何條where件下的count( *)的速度是非常快的,它無(wú)需計(jì)算行數(shù),可以直接捕獲這個(gè)值。但是當(dāng)有where條件的時(shí)候就和其他引擎沒(méi)有任何的區(qū)別了。
- 在MyISAM下的簡(jiǎn)單優(yōu)化
例如,查詢所有film_id大于5的數(shù)據(jù)行數(shù)。
explain select count(*) from film where film_id>5;
此時(shí)掃面了30行數(shù)據(jù)。
EXPLAIN SELECT
(SELECT count(*) FROM film) - count(*)
FROM
film
WHERE
film_id <= 5;
現(xiàn)在只掃描了6行?。。?/p>
- 統(tǒng)計(jì)同一列中不同值得數(shù)量
select count(color='red' or null) as red ,count(color='blue' or null)as blue from testcolor;
select sum(color='red') as red ,sum(color='blue')as blue from testcolor;
- 使用近似值
有時(shí)候我們統(tǒng)計(jì)數(shù)量的時(shí)候沒(méi)有必要非常的精確,可以使用近似的值代替,但是卻要比精確查詢快很多。
1.2優(yōu)化關(guān)聯(lián)查詢
- 確保在on或者using子句的列上有索引,在創(chuàng)建索引的時(shí)候需要考慮到關(guān)聯(lián)的順序,當(dāng)表A和表B用列c關(guān)聯(lián)的時(shí)候,如果優(yōu)化器關(guān)聯(lián)的順序是B,A那么沒(méi)有必要在B表對(duì)應(yīng)的列上創(chuàng)建索引,一般來(lái)說(shuō),沒(méi)有其他的理由,只需要在關(guān)聯(lián)順序中的第二個(gè)表上相應(yīng)的列創(chuàng)建索引。
- 確保分組和排序中的表達(dá)式只涉及到一個(gè)表中的列。
1.3優(yōu)化子查詢
在mysql5.6版本之前盡量使用關(guān)聯(lián)查詢代替子查詢,但是這并不是絕對(duì)的。
1.4優(yōu)化limit
對(duì)于limit,應(yīng)當(dāng)盡量使用“延遲關(guān)聯(lián)”,盡量掃描少的頁(yè)?;蛘咴诔绦蛑杏涗浬弦豁?yè),下一次分頁(yè)的時(shí)候從記錄開(kāi)始。
1.5優(yōu)化union
mysql總是通過(guò)創(chuàng)建并填充臨時(shí)表的方式執(zhí)行union查詢,除非確實(shí)要消除重復(fù)的行,否則一定要使用union all ,否則mysql會(huì)給臨時(shí)表加上distinct關(guān)鍵字,對(duì)臨時(shí)數(shù)據(jù)做唯一性檢查,這樣的代價(jià)是非常高的。
- 特殊的union查詢
一個(gè)union查詢,第一個(gè)子查詢先執(zhí)行,第二個(gè)子查詢后執(zhí)行,如果第一個(gè)查詢命中,則不執(zhí)行第二個(gè)子查詢,否則執(zhí)行第二個(gè)查詢。
select greatest(@found :=-1,id) as id ,'users' as which_tab1
from users where id=1
union all
select id from users_archived where id=1 and @found is NULL
union all
select 1 from dual where (@found :=null) is null;
1.6自定義變量
- 自定義變量做排名語(yǔ)句
select actor_id ,count(*) as cnt
from film
group by actor_id
order by cnt desc;
set @curr_cnt :=0,@prev_cnt :=0,@rank :=0;
select actor_id,
@curr_cnt :=cnt as cnt,
@rank :=if(@prev_cnt<>@curr_cnt ,@rank+1,@rank ) as rank,
@prev_cnt :=@curr_cnt as dummy
from (
select actor_id, count(*) as cnt from film
group by actor_id
order by cnt desc
)as der;
-避免重復(fù)查詢剛剛更新數(shù)據(jù)
update t1 set lastUpdate=now() where id=1;
select lastUpdate from t1 where id =1;
改寫(xiě)
update t1 set lastUpdate=now() where id=1 and @now :=now();
select @now;
無(wú)需訪問(wèn)表就可以拿到數(shù)據(jù)會(huì)快很多。
但是在使用用戶自定義變量的時(shí)候要注意取值的順序。