Mysql 數據類型隱式轉換規則

Mysql 數據類型隱式轉換規則

現象

今天遇到一個慢查詢,查詢日誌找到慢查詢語句是這樣的:html

select * from convert_test where areacode=0001 and period>='20170511' and period<='20170511';

convert_test表結構以下:mysql

CREATE TABLE `convert_test` (
    `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
    `areacode` char(12) NOT NULL DEFAULT '',
    `period` int(6) unsigned NOT NULL DEFAULT 0,
    `mid_price` int(10) unsigned NOT NULL DEFAULT 0,
    `mid_change` float NOT NULL DEFAULT 0,
    `updated_datetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    UNIQUE KEY `idx_areacode_period` (`areacode`,`period`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='隱式轉換測試表';

表中數據42W以上。git

乍一看,明明建立了一個惟一索引,正常來講,上面的查詢語句應該正好命中idx_areacode_period這個索引的,不該該是慢查詢的。github

爲了查看這個語句是怎麼查詢的,咱們在測試庫中explain一下:sql

mysql> explain select * from convert_test where areacode=0001 and period>='20170511' and period<='20170511';

結果以下:測試

explain

能夠看到,這裏是沒有用到索引的。spa

緣由

定義表的時候,areacode字段是字符串類型的,查詢的時候傳入的是0001,這裏0001被Mysql當作了整數處理爲1,Mysql檢測到areacode這個字段的查詢類型是整型,就會全表掃描,將全部行的areacode轉換成整型,而後在作查詢處理。日誌

找緣由了,就很好解決了,上面的sql語句修改以下:code

mysql> explain select * from convert_test where areacode='0001' and period>='20170511' and period<='20170511';

結果以下:htm

explain2

能夠看到徹底命中了idx_areacode_period 這個索引。

擴展

上面的period定義的時候是整型,可是查詢傳入的是字符串類型,那爲何會命中索引的呢?

看一下官方的隱試轉換說明:

  1. 兩個參數至少有一個是 NULL 時,比較的結果也是 NULL,例外是使用 <=> 對兩個 NULL 作比較時會返回 1,這兩種狀況都不須要作類型轉換
  2. 兩個參數都是字符串,會按照字符串來比較,不作類型轉換
  3. 兩個參數都是整數,按照整數來比較,不作類型轉換
  4. 十六進制的值和非數字作比較時,會被當作二進制串
  5. 有一個參數是 TIMESTAMP 或 DATETIME,而且另一個參數是常量,常量會被轉換爲 timestamp
  6. 有一個參數是 decimal 類型,若是另一個參數是 decimal 或者整數,會將整數轉換爲 decimal 後進行比較,若是另一個參數是浮點數,則會把 decimal 轉換爲浮點數進行比較
  7. 全部其餘狀況下,兩個參數都會被轉換爲浮點數再進行比較

因此,下面的幾個sql語句有相同的效果:

select * from convert_test where areacode=0001 and period>='20170511' and period<='20170511';
select * from convert_test where areacode=1 and period>='20170511' and period<='20170511';
select * from convert_test where areacode=0001.0 and period>='20170511' and period<='20170511';
select * from convert_test where areacode=1.0 and period>='20170511' and period<='20170511';

mysql 在查詢的時候,會將areacode轉換成浮點型進行比較。

首發:Mysql 數據類型隱式轉換規則

相關文章
相關標籤/搜索