explain作用
explain命令是用來(lái)查看一個(gè)sql語(yǔ)句的執(zhí)行計(jì)劃狡赐,可以看出這個(gè)sql語(yǔ)句是否使用到索引坟冲,是否合理可用脐彩。
explain返回參數(shù)說(shuō)明
- 作用于一個(gè)select sql語(yǔ)句:
explain select id from tb_delivery_user_owner where user_id=1;
得到如下圖結(jié)果:
2.作用于一個(gè)update sql:
explain update tb_delivery_user_owner set deleted = 0 where delivery_user_id=1;
重點(diǎn)解釋以下幾個(gè)字段:
type:這是重要的列惋鹅,顯示連接使用了何種類(lèi)型。從最好到最差的連接類(lèi)型為const悔据、eq_reg怎燥、ref、range蜜暑、index和ALL
type顯示的是訪問(wèn)類(lèi)型,是較為重要的一個(gè)指標(biāo)策肝,結(jié)果值從好到壞依次是:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL ,一般來(lái)說(shuō)肛捍,得保證查詢(xún)至少達(dá)到range級(jí)別,最好能達(dá)到ref之众。具體說(shuō)明拙毫,如下圖:
key: 實(shí)際使用的索引。如果為NULL棺禾,則沒(méi)有使用索引缀蹄。很少的情況下,MySQL會(huì)選擇優(yōu)化不足的索引。這種情況下缺前,可以在select語(yǔ)句中使用use index(indexname) 來(lái)強(qiáng)制使用一個(gè)索引或者用ignore index(indexname) 來(lái)強(qiáng)制MySQL忽略索引
key_len:使用的索引的長(zhǎng)度蛀醉。在不損失精確性的情況下,長(zhǎng)度越短越好衅码;也可以根據(jù)這個(gè)長(zhǎng)度判斷組合索引是用了部分字段還是所有字段拯刁。
ref:顯示索引的哪一列被使用了,如果可能的話(huà)逝段,是一個(gè)常數(shù)
rows:預(yù)計(jì)查詢(xún)掃描的數(shù)據(jù)行數(shù)
Extra:關(guān)于MySQL如何解析查詢(xún)的附加信息,如下圖所示:
explain實(shí)操
CREATE TABLE `tb_delivery_user_owner` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`delivery_user_id` int(11) NOT NULL COMMENT '投放賬號(hào)ID',
`user_id` int(11) NOT NULL COMMENT '使用者用戶(hù)ID',
`deleted` tinyint(1) NOT NULL DEFAULT '0',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_idx_delivery_owner` (`delivery_user_id`,`user_id`),
KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='投放賬號(hào)使用者表';
從建表sql知道表tb_delivery_user_owner有一個(gè)組合唯一索引uniq_idx_delivery_owner垛玻,索引的第一個(gè)字段為delivery_user_id,第二字段為user_id奶躯。
-
先看第一個(gè)sql語(yǔ)句:
image.png
顯然使用了索引:uniq_idx_delivery_owner帚桩,type=const表明基于索引查詢(xún),key_len=8說(shuō)明使用了完整的2個(gè)列嘹黔。
-
然后看第二個(gè)sql:
image.png
似乎也用到了索引账嚎,但是根據(jù)最左匹配原則,user_id作為第二個(gè)字段應(yīng)該用不到索引参淹。這是什么原因呢醉锄?最左匹配原則在這里不適用了嗎?
解釋?zhuān)?strong>這里是使用到索引浙值,但是type=index說(shuō)明是索引覆蓋掃描恳不,需要掃描整個(gè)索引表,實(shí)際上效果并不好开呐。根據(jù)最左匹配原則烟勋,user_id不滿(mǎn)足,但是它在組合索引列里筐付,所以直接查所有的索引卵惦。
接下來(lái)看下如果select的列不一樣是否有什么不同:
從圖上看到create_time字段不是索引列,當(dāng)它被select的時(shí)候直接就是全表掃描了瓦戚,這是因?yàn)閏reate_time不在索引表中沮尿,不能查索引表只能原表掃描〗辖猓可見(jiàn)查詢(xún)sql中畜疾,除了where條件外select的具體列也會(huì)有影響最終執(zhí)行性能。
總結(jié)
- explain用于查看sql執(zhí)行計(jì)劃印衔,可以分析是否用到索引啡捶,便于優(yōu)化sql
- explain的結(jié)果除了和where條件有關(guān),還和select的列有關(guān)奸焙。