MySQL實戰 | 18 爲什麼這些SQL語句邏輯相同,性能卻差異巨大? 案例一:條件字段函數操作 案例二:隱式類型轉換 案例三:隱式字符編碼轉換

在 MySQL 中,有很多看上去邏輯相同,但性能卻差異巨大的 SQL 語句。對這些語句使用不當的話,就會不經意間導致整個數據庫的壓力變大。

案例一:條件字段函數操作

假設有如下語句,並且字段 t_modified 上有索引:

mysql> select count(*) from tradelog where month(t_modified)=7;

那麼這條語句會很快地返回數據嗎?

答案是否定的。

對索引字段做函數操作,可能會破壞索引值的有序性,因此優化器就會放棄走樹索引。

這裏,由於加了 month() 函數操作,MySQL 無法再使用索引快速定位功能,而只能使用全索引掃描。

語句優化:

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');

案例二:隱式類型轉換

有如下語句:

mysql> select * from tradelog where tradeid=110717;

tradeid 字段是 varchar(32) 類型的,而對比的參數是整數,所有就需要做類型轉換。

1、數據類型轉換的規則是什麼?

select "10" > 9 的結果:

① 如果結果是 1,那麼就是將字符串轉換成數字
② 如果結果是 0,那麼就是將數字轉換成字符串

如果是將字符串轉換成數字,那麼上面的語句對應的就是:

mysql> select * from tradelog where  CAST(tradid AS signed int) = 110717;

其實就出發了案例一里面的規則,對字符串索引進行了函數操作,優化器就會放棄樹搜索的功能,進行全表搜索。

案例三:隱式字符編碼轉換

如下語句:

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 內部的操作是,先把 utf8 字符串轉成 utf8mb4 字符集,再做比較。

同樣,觸發了案例一中的條件。


關注本公衆號,後臺回覆「2018」即可獲取傳智播客 2018 最新 Python 和 Java 教程。

公衆號提供CSDN資源免費下載服務!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章