今天遇到乙個慢查詢,查詢日誌找到慢查詢語句是這樣的:
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,則另乙個運算元被轉換為...