在 MySQL 中,有很多看上去邏輯相同,但性能卻差異巨大的 SQL 語句。對這些語句使用不當?shù)脑挘蜁唤?jīng)意間導致整個數(shù)據(jù)庫的壓力變大。
案例一:條件字段函數(shù)操作
假設(shè)有如下語句,并且字段 t_modified 上有索引:
mysql> select count(*) from tradelog where month(t_modified)=7;
那么這條語句會很快地返回數(shù)據(jù)嗎?
答案是否定的。
對索引字段做函數(shù)操作,可能會破壞索引值的有序性,因此優(yōu)化器就會放棄走樹索引。
這里,由于加了 month() 函數(shù)操作,MySQL 無法再使用索引快速定位功能,而只能使用全索引掃描。
語句優(yōu)化:
mysql> select count(*) from tradelog where
-> (t_modified >= '2016-7-1' and t_modified<'2016-8-1') or
-> (t_modified >= '2017-7-1' and t_modified<'2017-8-1') or
-> (t_modified >= '2018-7-1' and t_modified<'2018-8-1');
案例二:隱式類型轉(zhuǎn)換
有如下語句:
mysql> select * from tradelog where tradeid=110717;
tradeid 字段是 varchar(32) 類型的,而對比的參數(shù)是整數(shù),所有就需要做類型轉(zhuǎn)換。
1、數(shù)據(jù)類型轉(zhuǎn)換的規(guī)則是什么?
看 select "10" > 9
的結(jié)果:
① 如果結(jié)果是 1,那么就是將字符串轉(zhuǎn)換成數(shù)字;
② 如果結(jié)果是 0,那么就是將數(shù)字轉(zhuǎn)換成字符串;
如果是將字符串轉(zhuǎn)換成數(shù)字,那么上面的語句對應的就是:
mysql> select * from tradelog where CAST(tradid AS signed int) = 110717;
其實就出發(fā)了案例一里面的規(guī)則,對字符串索引進行了函數(shù)操作,優(yōu)化器就會放棄樹搜索的功能,進行全表搜索。
案例三:隱式字符編碼轉(zhuǎn)換
如下語句:
mysql> select d.* from tradelog l, trade_detail d where d.tradeid=l.tradeid and l.id=2; /* 語句 Q1*/
如果表 tradelog(utf8) 和表 trade_detail(utf8mb4) 的字符集不同,那么 d.tradeid=l.tradeid
條件也會導致全表掃描。
字符集 utf8mb4 是 utf8 的超集,所以當這兩個類型的字符串在做比較的時候,MySQL 內(nèi)部的操作是,先把 utf8 字符串轉(zhuǎn)成 utf8mb4 字符集,再做比較。
同樣,觸發(fā)了案例一中的條件。
關(guān)注本公眾號,后臺回復「2018」即可獲取傳智播客 2018 最新 Python 和 Java 教程。
公眾號提供CSDN資源免費下載服務!