type:前三個(gè)的 type 值為 index,表示全索引掃描,就是把整個(gè)索引過一遍就行(注意是索引不是整個(gè)表);后兩個(gè)的 type 值為 all,表示全表掃描,即不會使用索引。 key:這個(gè)表示 MySQL 決定采用哪個(gè)索引來優(yōu)化對該表的訪問,PRIMARY 表示利用主鍵索引,NULL 表示不用索引。 key_len:這個(gè)表示 MySQL 使用的鍵長度,因?yàn)槲覀兊闹麈I類型是 INT 且非空,所以值為 4。 Extra:這個(gè)中的 Using index 表示優(yōu)化器只需要通過訪問索引就可以獲取到需要的數(shù)據(jù)(不需要回表)。 通過 explain 我們其實(shí)也能大概看出來前三種統(tǒng)計(jì)方式的執(zhí)行效率是要高一些的(因?yàn)橛玫搅怂饕竺鎯煞N的統(tǒng)計(jì)效率相對來說要低一些的(沒用索引,需要全表掃描)。
對于 select count(1) from user; 這個(gè)查詢來說,InnoDB 引擎會去找到一個(gè)最小的索引樹去遍歷(不一定是主鍵索引),但是不會讀取數(shù)據(jù),而是讀到一個(gè)葉子節(jié)點(diǎn),就返回 1,最后將結(jié)果累加。
對于 select count(id) from user; 這個(gè)查詢來說,InnoDB 引擎會遍歷整個(gè)主鍵索引,然后讀取 id 并返回,不過因?yàn)?id 是主鍵,就在 B+ 樹的葉子節(jié)點(diǎn)上,所以這個(gè)過程不會涉及到隨機(jī) IO(并不需要回表等操作去數(shù)據(jù)頁拿數(shù)據(jù)),性能也是 OK 的。
對于 select count(username) from user; 這個(gè)查詢來說,InnoDB 引擎會遍歷整張表做全表掃描,讀取每一行的 username 字段并返回,如果 username 在定義時(shí)候設(shè)置了 not null,那么直接統(tǒng)計(jì) username 的個(gè)數(shù);如果 username 在定義的時(shí)候沒有設(shè)置 not null,那么就先判斷一下 username 是否為空,然后再統(tǒng)計(jì)。
最后再來說說 select count(*) from user; ,這個(gè) SQL 的特殊之處在于它被 MySQL 優(yōu)化過,當(dāng) MySQL 看到 count(*) 就知道你是想統(tǒng)計(jì)總記錄數(shù),就會去找到一個(gè)最小的索引樹去遍歷,然后統(tǒng)計(jì)記錄數(shù)。