Mysql 資料型別隱式轉換規則

2021-09-25 01:20:22 字數 3156 閱讀 1327

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

select

*from convert_test where areacode=

0001

and period>=

'20170511'

and period<=

'20170511'

;

convert_test表結構如下:

create

table

`convert_test`

(`id`

bigint(20

)unsigned

notnull

auto_increment

,`areacode`

char(12

)not

null

default'',

`period`

int(6)

unsigned

notnull

default0,

`mid_price`

int(10)

unsigned

notnull

default0,

`mid_change`

float

notnull

default0,

`updated_datetime`

timestamp

notnull

default

current_timestamp

onupdate

current_timestamp

,primary

key(

`id`),

unique

key`idx_areacode_period`

(`areacode`

,`period`))

engine

=innodb

default

charset

=utf8 comment

='隱式轉換測試表'

;

表中資料42w以上。

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

為了檢視這個語句是怎麼查詢的,我們在測試庫中explain一下:

mysql>

explain

select

*from convert_test where areacode=

0001

and period>=

'20170511'

and period<=

'20170511'

;

結果如下:

[外鏈轉存失敗(img-6gbvdjsu-1562402055518)(/images/posts/2017/github_blogexplain.png)]

可以看到,這裡是沒有用到索引的。

定義表的時候,areacode欄位是字串型別的,查詢的時候傳入的是0001,這裡0001被mysql當做了整數處理為1,mysql檢測到areacode這個欄位的查詢型別是整型,就會全表掃瞄,將所有行的areacode轉換成整型,然後在做查詢處理。

找原因了,就很好解決了,上面的sql語句修改如下:

mysql>

explain

select

*from convert_test where areacode=

'0001'

and period>=

'20170511'

and period<=

'20170511'

;

結果如下:

[外鏈轉存失敗(img-pk9tx7if-1562402055520)(/images/posts/2017/github_blogexplain2.png)]

可以看到完全命中了idx_areacode_period 這個索引。

上面的period定義的時候是整型,但是查詢傳入的是字串型別,那為什麼會命中索引的呢?

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

兩個引數至少有乙個是 null 時,比較的結果也是 null,例外是使用 <=> 對兩個 null 做比較時會返回 1,這兩種情況都不需要做型別轉換

兩個引數都是字串,會按照字串來比較,不做型別轉換

兩個引數都是整數,按照整數來比較,不做型別轉換

十六進製制的值和非數字做比較時,會被當做二進位制串

有乙個引數是 timestamp 或 datetime,並且另外乙個引數是常量,常量會被轉換為 timestamp

有乙個引數是 decimal 型別,如果另外乙個引數是 decimal 或者整數,會將整數轉換為 decimal 後進行比較,如果另外乙個引數是浮點數,則會把 decimal 轉換為浮點數進行比較

所有其他情況下,兩個引數都會被轉換為浮點數再進行比較

所以,下面的幾個sql語句有相同的效果:

select

*from convert_test where areacode=

0001

and period>=

'20170511'

and period<=

'20170511'

;select

*from convert_test where areacode=

1and 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.0and period>=

'20170511'

and period<=

'20170511'

;

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

mysql隱時型別轉換規則 MYSQL隱式型別轉換

mysql隱式型別轉換 關於官方文件中的理解大致是 如果兩個引數比較,有至少乙個null,結果就是null,除了是用null null 會返回1。不做型別轉換 兩個引數都是字串,按照字串比較。不做型別轉換 兩個引數都是整數,按照整數比較。不做型別轉換 如果不與數字進行比較,則將十六進製制值視為二進位...

C語言資料型別隱式轉換規則

c語言裡有各種資料型別,包含char,uchar,short,ushort,int,uint,long,ulong,float,double。每種數值型別能表達的值的範圍是不同的,而c c 的編譯器又允許這幾種型別之間進行混合運算,這就帶來了型別轉換問題。c語言隱式轉換規則簡單來說就是先進行整型提公...

C語言隱式型別轉換規則

先看程式 include include int main int argc,char argv 執行結果是 1 1 解釋 按步驟進行.1.如果其中乙個運算元為long double型別,則另乙個運算元被轉換為long double.2.否則,如果其中乙個運算元為double,則另乙個運算元被轉換為...