本文來自於:
https://dev.mysql.com/doc/refman/5.6/en/group-by-functions.html#function_count
https://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_count
https://dev.mysql.com/doc/refman/8.0/en/group-by-functions.html#function_count
目錄
一、對於InnoDB
COUNT(col_name)
對於 查詢結果集中的 每一行,如果 col_name 是 non-null,則加1,最後得到的數字 即爲 COUNT(col_name)
COUNT(*) 和 COUNT(1)
1. 查詢結果集的 行數量 即爲 COUNT(*)或COUNT(1),不關心 行null 或 行non-null
2. 兩者 不存在 任何的性能差距(InnoDB處理兩者的方式完全一樣)
MySQL 5.6, 5.7, 8.0的官方文檔明確指出(之前老版本應該也是一樣,但,沒去翻其他版本的文檔):
InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.
InnoDB處理 SELECT COUNT(*) 的方式
1. 5.7.18之前,InnoDB通過掃描 聚集索引(clustered index) 來處理 SELECT COUNT(*)
2. 5.7.18及以後
a. InnoDB通過遍歷 可用的最小的輔助索引(secondary index) 來處理 SELECT COUNT(*)
b. 當不存在 輔助索引(secondary index)時,則通過 掃描聚集索引(clustered index) 來處理 SELECT COUNT(*)
如果索引記錄並未完全裝入buffer pool,處理 SELECT COUNT(*)還是需要花費點時間的,所以,如果並不需要 精確的COUNT數量,可以使用 SHOW TABLE STATUS
使用“InnoDB引擎,MySQL 5.6.23-72.1-log”來驗證下
drop table if exists `test_count`;
CREATE TABLE `test_count` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`var_col1` varchar(64),
`var_col2` varchar(64),
primary key `pk_id` (`id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='測試count函數';
insert into test_count(var_col1, var_col2) values ('a1', 'b');
insert into test_count(var_col1, var_col2) values (null, 'b');
insert into test_count(var_col1, var_col2) values (null, null);
select
count(1), -- 3
count(*), -- 3
count(var_col1), -- 1
count(var_col2), -- 2
-- count(var_col1, var_col2), 語法錯誤
count(distinct var_col1, var_col2) -- 1。只要某個列爲null,則不包括
from test_count;
SHOW TABLE STATUS where name='test_count';
二、對於MyISAM
MyISAM COUNT(*)
MyISAM 爲行數量 存儲了一個確切數字,所以同時滿足下面條件時,SELECT COUNT(*)非常快
1. 只查詢 單一一個表,且,
2. 不查詢 其他列,且,
3. 不存在 WHERE 條件
例如:SELECT COUNT(*) FROM student; 非常快
MyISAM 的COUNT(1)
COUNT(1) is only subject to the same optimization if the first column is defined as NOT NULL
沒看懂這是啥意思
Enjoy