count(1),count(*),count(主键) 性能对比及辟谣
分享一波:程序員賺外快-必看的巔峰干貨
前言
前段時間關(guān)于統(tǒng)計(jì)數(shù)量的sql問題和朋友進(jìn)行了討論,網(wǎng)上關(guān)于這三種查詢方式說法不一,主要有以下兩種說法。
count(*) = count(主鍵) > count(1) count(主鍵) > count(*) > count(1)今天對這三種方式進(jìn)行探究。
數(shù)據(jù)庫為mysql 5.7.12,引擎為InnoDB。
建表
CREATE TABLE user (
id int(32) NOT NULL AUTO_INCREMENT,
name varchar(500) DEFAULT NULL COMMENT ‘姓名’,
deleted int(2) NOT NULL DEFAULT ‘1’ COMMENT ‘邏輯刪除’,
created_date datetime DEFAULT NULL COMMENT ‘創(chuàng)建時間’,
created_by varchar(255) DEFAULT NULL,
update_date datetime DEFAULT NULL,
update_by varchar(255) DEFAULT NULL,
version int(11) NOT NULL DEFAULT ‘1’ COMMENT ‘樂觀鎖’,
PRIMARY KEY (id) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1502726 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT=‘用戶表’;
循環(huán)插入150萬條數(shù)據(jù)。
DROP PROCEDURE
IF
EXISTS proc_initData;
DELIMITER $
CREATE PROCEDURE proc_initData () BEGIN
DECLARE
i INT DEFAULT 1;
WHILE
i <= 5000000 DO
INSERT INTO user ( name, created_date, update_date )
VALUES
( ‘哈哈哈啊哈哈哈’, NOW(), NOW() );
END $ CALL proc_initData ();
這里需要使用到mysql的explain關(guān)鍵字,對count(1),count(*),count(id),count(name)分別查看性能
explain select count(1) from user
explain select count(*) from user
explain select count(id) from user
explain select count(name) from user
可以看出,select count(1)、count(*)、count(id)的執(zhí)行計(jì)劃是一毛一樣的。多次執(zhí)行取平均值,三者的性能也是非常趨近,因此可以認(rèn)為三者性能相同。這里我加了個count(name)進(jìn)行對比,并將最后30萬條數(shù)據(jù)的name置空,可以看出性能有明顯的差別。
mysql底層對count查詢做了優(yōu)化,當(dāng)mysql確定count中的列名不為空時,實(shí)際上就是在統(tǒng)計(jì)行數(shù)。那么mysql內(nèi)部會將count(列名)優(yōu)化為count(*) —— 出自《高性能MySQL》一書
也就是說count(1)和count(主鍵字段)還是要優(yōu)化到count()的,而如果只是統(tǒng)計(jì)某個列,只要該列不為空,無論是否為索引,都會被優(yōu)化為count(),因此三者性能并無任何差異。官方文檔對其也進(jìn)行了解釋。
InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.
https://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_count
至此,事實(shí)上并未解決關(guān)于這個問題的疑惑。上面的內(nèi)容都在強(qiáng)調(diào)“Mysql”,就是說,上面的驗(yàn)證可能僅對MySql有效,其他的數(shù)據(jù)庫可能未必會對count語句進(jìn)行優(yōu)化。因此我又通過SQLServer去驗(yàn)證。
因?yàn)槲冶镜夭]有安裝SQLServer,因此我是直接使用公司的開發(fā)庫進(jìn)行驗(yàn)證,這里不方便截圖,直接說明一下200萬條數(shù)據(jù)驗(yàn)證結(jié)果。
列名為主鍵,count(列名)會比count(1)快 列名不為主鍵,count(1)會比count(列名)快 如果表多個列并且沒有主鍵,則 count(1) 的執(zhí)行效率優(yōu)于 count(*) 如果有主鍵,則 select count(主鍵)的執(zhí)行效率是最優(yōu)的 如果表只有一個字段,則 select count(*)最優(yōu)。可見,在SQLServer中,count(*)的性能并沒有count(主鍵)高。
結(jié)語
根據(jù)上面對兩個數(shù)據(jù)庫的驗(yàn)證得出結(jié)論:不說是什么數(shù)據(jù)庫都是耍流氓!SQL標(biāo)準(zhǔn)只提供了count這個內(nèi)置函數(shù),所有的數(shù)據(jù)庫需要遵循這個標(biāo)準(zhǔn),但是不同的數(shù)據(jù)庫對于count的處理不同。在mysql中建議寫count(*),而在SQLServer中建議寫count(主鍵),在PostgreSql以及其他數(shù)據(jù)庫中并未對其進(jìn)行驗(yàn)證
分享一波:程序員賺外快-必看的巔峰干貨
如果以上內(nèi)容對你覺得有用,并想獲取更多的賺錢方式和免費(fèi)的技術(shù)教程
請關(guān)注微信公眾號:HB荷包
一個能讓你學(xué)習(xí)技術(shù)和賺錢方法的公眾號,持續(xù)更新
總結(jié)
以上是生活随笔為你收集整理的count(1),count(*),count(主键) 性能对比及辟谣的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 进入IT行业,要不要参加培训班?
- 下一篇: ios10不能定位 window.nav