MySQL 中 count(*) 比 count(1) 快?
往期熱門文章: 1、用Stream來優(yōu)化老代碼,瞬間干凈優(yōu)雅了!
3、自定義注解妙用,一行代碼搞定用戶操作日志記錄,你學會了嗎?
count(1) 比 count(*) 快,這能忍?必須得和他掰扯掰扯。1.實踐
CREATE?TABLE?`user`?(
??`id`?int(11)?unsigned?NOT?NULL?AUTO_INCREMENT,
??`username`?varchar(255)?DEFAULT?NULL,
??`address`?varchar(255)?DEFAULT?NULL,
??`password`?varchar(255)?DEFAULT?NULL,
??PRIMARY?KEY?(`id`)
)?ENGINE=InnoDB?DEFAULT?CHARSET=utf8mb4;


2. explain 分析

type:前三個的 type 值為 index,表示全索引掃描,就是把整個索引過一遍就行(注意是索引不是整個表);后兩個的 type 值為 all,表示全表掃描,即不會使用索引。 key:這個表示 MySQL 決定采用哪個索引來優(yōu)化對該表的訪問,PRIMARY 表示利用主鍵索引,NULL 表示不用索引。 key_len:這個表示 MySQL 使用的鍵長度,因為我們的主鍵類型是 INT 且非空,所以值為 4。 Extra:這個中的 Using index 表示優(yōu)化器只需要通過訪問索引就可以獲取到需要的數(shù)據(jù)(不需要回表)。
3. 原理分析
3.1 主鍵索引與普通索引

3.2 原理分析
select count(1) from user; 這個查詢來說,InnoDB 引擎會去找到一個最小的索引樹去遍歷(不一定是主鍵索引),但是不會讀取數(shù)據(jù),而是讀到一個葉子節(jié)點,就返回 1,最后將結果累加。select count(id) from user; ?這個查詢來說,InnoDB 引擎會遍歷整個主鍵索引,然后讀取 id 并返回,不過因為 id 是主鍵,就在 B+ 樹的葉子節(jié)點上,所以這個過程不會涉及到隨機 IO(并不需要回表等操作去數(shù)據(jù)頁拿數(shù)據(jù)),性能也是 OK 的。select count(username) from user; ?這個查詢來說,InnoDB 引擎會遍歷整張表做全表掃描,讀取每一行的 username 字段并返回,如果 username 在定義時候設置了 not null,那么直接統(tǒng)計 username 的個數(shù);如果 username 在定義的時候沒有設置 not null,那么就先判斷一下 username 是否為空,然后再統(tǒng)計。select count(*) from user; ,這個 SQL 的特殊之處在于它被 MySQL 優(yōu)化過,當 MySQL 看到 count(*) 就知道你是想統(tǒng)計總記錄數(shù),就會去找到一個最小的索引樹去遍歷,然后統(tǒng)計記錄數(shù)。explain select count(*) from user; 的執(zhí)行計劃:
4. MyISAM 呢?
select count(*) from user; 操作執(zhí)行起來是非??斓?,那是因為 MyISAM 把表中的行數(shù)直接存在磁盤中了,需要的時候直接讀取出來就行了,所以非常快。
往期熱門文章:
1、《歷史文章分類導讀列表!精選優(yōu)秀博文都在這里了!》 2、程序員裸辭全職接單一個月的感觸 3、Java8 Stream:2萬字20個實例,玩轉集合的篩選、歸約、分組、聚合 4、字節(jié)終面:兩個文件的公共URL怎么找? 5、留在一線,逃離一線?我從上海舉家回成都的生活經(jīng)歷告訴你 6、公司規(guī)定所有接口都用 POST請求,這是為什么? 7、我被這個瀏覽了 746000 次的問題驚住了! 8、騰訊三面:40億個QQ號碼如何去重? 9、自從用完Gradle后,有點嫌棄Maven了!速度賊快! 10、一個員工的離職成本有多恐怖!
評論
圖片
表情
