目標(biāo)
分析子查詢時(shí)對(duì)索引的利用
例子
- 還是tbl_trx_order訂單表,和另外一張支付訂單表tbl_pay_order, PAY_EXTERNAL_NO 表中CREATE_TIME是索引字段, tbl_trx_order 表中tbl_trx_order 是索引字段,sql如下,此時(shí)會(huì)用索引嗎
explain SELECT * FROM tbl_trx_order where PAY_EXTERNAL_NO in ( select PAY_EXTERNAL_NO from tbl_pay_order where CREATE_TIME >'2017-11-13 15:00:27' )
- 將in改為=號(hào),此時(shí)會(huì)用索引嗎
explain SELECT * FROM tbl_trx_order where PAY_EXTERNAL_NO = ( select PAY_EXTERNAL_NO from tbl_pay_order where CREATE_TIME ='2018-07-05 11:19:25' )
分析
網(wǎng)上有很多博客說,mysql的in是不會(huì)使用索引的,親測了下,這么說不完全正確.
看下上面兩個(gè)sql的執(zhí)行計(jì)劃
顯然,sql1中in的方式我們并沒有用到索引,而子查詢=到方式,索引是生效的.但其實(shí)也有特殊情況,如過此時(shí)我的tbl_pay_order子表的pay_external_no也是有索引的,再來看下執(zhí)行計(jì)劃
發(fā)現(xiàn)此時(shí)查詢tbl_trx_order是會(huì)用到從tbl_pay_order查詢出的pay_external_No索引進(jìn)行索引匹配.所以這個(gè)時(shí)候索引是生效的.
但下面我們把sql1中的時(shí)間改下,再來試一下
explain SELECT * from tbl_trx_order where PAY_EXTERNAL_NO in ( select PAY_EXTERNAL_NO from tbl_pay_order where CREATE_TIME >'2017-10-13 15:00:27' )
執(zhí)行計(jì)劃如下
我們發(fā)現(xiàn),上面出現(xiàn)的索引生效又突然失效了!!!這是因?yàn)閙ysql對(duì)于not in ,!=這種肯定是沒有索引,但>脑又、<這種范圍型的索引生效情況,mysql會(huì)自動(dòng)進(jìn)行優(yōu)化,如果使用索引比查全表節(jié)省時(shí)間,mysql會(huì)去使用索引,否則這種情況不會(huì)用索引.
另外,我們發(fā)現(xiàn)子表中的索引失效的時(shí)候,外層表的索引一樣會(huì)聯(lián)動(dòng)失效.綜合考慮,in最好少用.