最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入剖析MySQL中COUNT(id)和COUNT(*)哪個(gè)效率更高

 更新時(shí)間:2026年07月26日 08:48:45   作者:detayun  
還在為MySQL中COUNT(*)和COUNT(id)的性能糾結(jié)嗎,本文將深入剖析MySQL InnoDB引擎下COUNT操作的優(yōu)化原理并澄清常見誤區(qū),感興趣的小伙伴可以了解下

前言

開發(fā)工作中統(tǒng)計(jì)行數(shù),經(jīng)常會(huì)寫出兩種寫法:

SELECT COUNT(*) FROM `user_login_log` WHERE `date` = CURDATE();
SELECT COUNT(id) FROM `user_login_log` WHERE `date` = CURDATE();

網(wǎng)上充斥大量老舊傳言:COUNT(*) 需要掃描整行數(shù)據(jù),COUNT(id) 只讀取主鍵,COUNT(id) 速度更快。

這條說(shuō)法放到現(xiàn)在 InnoDB 引擎下是錯(cuò)誤謠言。

本文結(jié)合 InnoDB 底層原理,講清楚 COUNT(*)、COUNT(id)COUNT(普通字段) 的差異,給出生產(chǎn)環(huán)境標(biāo)準(zhǔn)編碼規(guī)范。

前置環(huán)境:本文全部基于 MySQL InnoDB(5.7 / 8.0,線上最通用);MyISAM 機(jī)制不一樣,文末單獨(dú)說(shuō)明。

一、先搞懂三個(gè)COUNT語(yǔ)法的語(yǔ)義

1. COUNT(*)

SQL標(biāo)準(zhǔn)定義:統(tǒng)計(jì)滿足查詢條件的所有行數(shù),不做任何 NULL 判斷。

MySQL官方專門對(duì) COUNT(*) 做優(yōu)化,優(yōu)化器會(huì)選擇當(dāng)前表體積最小的二級(jí)索引進(jìn)行掃描計(jì)數(shù),不需要讀取聚簇索引完整行數(shù)據(jù)。

2. COUNT(id)

語(yǔ)義:統(tǒng)計(jì) id IS NOT NULL 的記錄行數(shù)。

一般業(yè)務(wù)中 id 為主鍵,主鍵字段強(qiáng)制非空,所以邏輯等價(jià)統(tǒng)計(jì)總行數(shù)。

執(zhí)行邏輯:掃描索引,讀取主鍵id的值,判斷不為NULL后計(jì)數(shù)。

3. COUNT(普通業(yè)務(wù)字段)

COUNT(login_ip)

語(yǔ)義:統(tǒng)計(jì) login_ip IS NOT NULL 的記錄。

風(fēng)險(xiǎn)兩點(diǎn):

  1. 如果字段允許NULL,統(tǒng)計(jì)結(jié)果和真實(shí)行數(shù)不一致,產(chǎn)生業(yè)務(wù)BUG;
  2. InnoDB需要取出字段真實(shí)值判斷NULL,開銷高于 COUNT(*)。

二、核心結(jié)論(InnoDB)

帶WHERE條件統(tǒng)計(jì)時(shí),COUNT(*) 和 COUNT(id) 性能幾乎沒有差距。

不要耗費(fèi)精力糾結(jié)二者選擇,二者執(zhí)行計(jì)劃、掃描行數(shù)、IO開銷基本持平。

底層原因:InnoDB二級(jí)索引葉子節(jié)點(diǎn)本身就存放主鍵id。

無(wú)論優(yōu)化器選擇二級(jí)索引掃描計(jì)數(shù):

  • COUNT(*):只需要計(jì)數(shù)索引條目,不需要讀取字段值
  • COUNT(id):除了計(jì)數(shù),還要額外取出id值做非空判斷

理論上 COUNT(*) 會(huì)略微優(yōu)于 COUNT(id),只是絕大多數(shù)場(chǎng)景差距感知不到。

三、誤區(qū)拆解:為什么會(huì)流傳 COUNT(id) 更快?

謠言來(lái)源大多是老舊MyISAM認(rèn)知混淆,以及早期網(wǎng)絡(luò)文章以訛傳訛:

  1. MyISAM無(wú)WHERE條件 COUNT(*) 超快,引擎緩存總行數(shù);但MyISAM早已不是主流;
  2. 很多人主觀猜想:* 代表讀取整行數(shù)據(jù),實(shí)際上MySQL優(yōu)化器根本不會(huì)讀取完整行;
  3. 沒有區(qū)分「有無(wú)WHERE條件」,籠統(tǒng)下定論。

重點(diǎn)糾正:InnoDB中,COUNT(*) 不會(huì)讀取完整一行數(shù)據(jù),優(yōu)化器只利用索引條目數(shù)量統(tǒng)計(jì)。

四、無(wú)WHERE條件的特殊場(chǎng)景

-- 查詢整張表總條數(shù)
SELECT COUNT(*) FROM `user`;
SELECT COUNT(id) FROM `user`;

很多人發(fā)現(xiàn)這條SQL查詢很慢。

原因:InnoDB事務(wù)多版本機(jī)制,沒有辦法緩存表總行數(shù),無(wú)論 COUNT(*) / COUNT(id) 都必須掃描索引統(tǒng)計(jì),二者速度依舊基本一致。

想要高頻查詢表總量提速:使用Redis緩存、定時(shí)統(tǒng)計(jì)表總數(shù),避免頻繁COUNT掃描索引。

五、新增對(duì)比:COUNT(常量)

額外拓展一個(gè)寫法:

SELECT COUNT(1) FROM `user_login_log` WHERE `date` = CURDATE();

在新版本MySQL中,COUNT(1) 會(huì)被優(yōu)化器等價(jià)優(yōu)化成 COUNT(*),性能同樣持平。

不用盲目推崇COUNT(1)。

六、一張表清晰區(qū)分三種寫法

寫法作用是否判NULL性能建議風(fēng)險(xiǎn)
COUNT(*)統(tǒng)計(jì)所有符合條件行不判斷NULL?推薦,官方標(biāo)準(zhǔn)無(wú)
COUNT(id)統(tǒng)計(jì)id不為NULL的行判斷NULL可用,略遜于COUNT(*)id必須為主鍵非空,否則結(jié)果異常
COUNT(login_ip)統(tǒng)計(jì)login_ip不為NULL的行判斷NULL?不推薦字段存在NULL時(shí)統(tǒng)計(jì)數(shù)量失真,開銷更大

七、線上編碼規(guī)范建議

優(yōu)先使用 COUNT(*),遵循SQL標(biāo)準(zhǔn),語(yǔ)義清晰,MySQL官方推薦;

-- 標(biāo)準(zhǔn)寫法
SELECT COUNT(*) AS active_num FROM user_login_log WHERE `date` = CURDATE();

禁止使用 COUNT(普通業(yè)務(wù)字段) 統(tǒng)計(jì)表總行數(shù);

如果需要統(tǒng)計(jì)「某字段不為空」的數(shù)據(jù),才使用 COUNT(字段名);

-- 合理場(chǎng)景:統(tǒng)計(jì)有登錄IP的用戶
SELECT COUNT(login_ip) FROM user_login_log WHERE `date` = CURDATE();

不要為了“優(yōu)化性能”把 COUNT(*) 強(qiáng)行改成 COUNT(id),屬于無(wú)效優(yōu)化;

大表頻繁全量COUNT統(tǒng)計(jì),使用緩存預(yù)聚合方案。

八、實(shí)戰(zhàn)驗(yàn)證方式

使用EXPLAIN對(duì)比兩條SQL執(zhí)行計(jì)劃:

EXPLAIN SELECT COUNT(*) FROM user_login_log WHERE `date` = CURDATE();
EXPLAIN SELECT COUNT(id) FROM user_login_log WHERE `date` = CURDATE();

觀察輸出:type、key、rows基本完全一致,可以直觀證明性能差距極小。

九、補(bǔ)充:MyISAM簡(jiǎn)要區(qū)分(了解即可)

MyISAM引擎內(nèi)部保存表總行數(shù):

SELECT COUNT(*) FROM `user`; -- 不加WHERE,瞬間返回

但只要帶上WHERE條件,MyISAM同樣需要掃描數(shù)據(jù),此時(shí) COUNT(*)COUNT(id) 同樣差距不大。

新項(xiàng)目基本不會(huì)使用MyISAM,僅作知識(shí)拓展。

十、全文總結(jié)

  1. InnoDB引擎下,COUNT(*)COUNT(id) 性能幾乎持平,COUNT(*) 理論小幅領(lǐng)先;
  2. 網(wǎng)傳「COUNT(id)速度更快」屬于過(guò)時(shí)謠言,不要作為優(yōu)化依據(jù);
  3. 統(tǒng)計(jì)滿足條件全部行數(shù),統(tǒng)一使用 COUNT(*);
  4. 杜絕用 COUNT(普通字段) 統(tǒng)計(jì)總行數(shù),存在邏輯BUG與性能損耗;
  5. SQL優(yōu)化把重心放在索引設(shè)計(jì),不要在COUNT寫法上做無(wú)效內(nèi)卷。

寫代碼記住一條準(zhǔn)則:先保證語(yǔ)義準(zhǔn)確,再追求性能;符合SQL標(biāo)準(zhǔn)的 COUNT(*) 是兼顧可讀性與性能的最優(yōu)選擇。

以上就是深入剖析MySQL中COUNT(id)和COUNT(*)哪個(gè)效率更高的詳細(xì)內(nèi)容,更多關(guān)于MySQL COUNT(id)和COUNT(*)對(duì)比的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • MySQL的DELETE刪除數(shù)據(jù)示例詳解

    MySQL的DELETE刪除數(shù)據(jù)示例詳解

    MySQL的DELETE語(yǔ)句用于從數(shù)據(jù)庫(kù)表中刪除記錄,本文將詳細(xì)介紹DELETE語(yǔ)句的基本語(yǔ)法、高級(jí)用法、性能優(yōu)化策略以及注意事項(xiàng),感興趣的朋友跟隨小編一起看看吧
    2024-12-12
  • MySQL報(bào)錯(cuò)1118,數(shù)據(jù)類型長(zhǎng)度過(guò)長(zhǎng)問(wèn)題及解決

    MySQL報(bào)錯(cuò)1118,數(shù)據(jù)類型長(zhǎng)度過(guò)長(zhǎng)問(wèn)題及解決

    在使用MySQL過(guò)程中,常見的一個(gè)問(wèn)題是報(bào)錯(cuò)1118,這通常發(fā)生在創(chuàng)建表時(shí),錯(cuò)誤提示為“Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual
    2024-10-10
  • mysql 5.7.21 解壓版安裝配置方法圖文教程

    mysql 5.7.21 解壓版安裝配置方法圖文教程

    這篇文章主要為大家詳細(xì)介紹了mysql 5.7.21 解壓版安裝配置方法圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • 關(guān)于B+樹的使用及說(shuō)明

    關(guān)于B+樹的使用及說(shuō)明

    這篇文章主要介紹了關(guān)于B+樹的使用及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-06-06
  • MySQL中實(shí)現(xiàn)行列轉(zhuǎn)換的操作示例

    MySQL中實(shí)現(xiàn)行列轉(zhuǎn)換的操作示例

    在 MySQL 中進(jìn)行行列轉(zhuǎn)換(即,將某些列轉(zhuǎn)換為行或?qū)⒛承┬修D(zhuǎn)換為列)通常涉及使用條件邏輯和聚合函數(shù),本文給大家介紹了MySQL中實(shí)現(xiàn)行列轉(zhuǎn)換的操作示例,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下
    2024-06-06
  • MySQL數(shù)據(jù)庫(kù)常用操作技巧總結(jié)

    MySQL數(shù)據(jù)庫(kù)常用操作技巧總結(jié)

    這篇文章主要介紹了MySQL數(shù)據(jù)庫(kù)常用操作技巧,結(jié)合實(shí)例形式總結(jié)分析了mysql查詢、存儲(chǔ)過(guò)程、字符串截取、時(shí)間、排序等常用操作技巧,需要的朋友可以參考下
    2018-03-03
  • MySQL入門(二) 數(shù)據(jù)庫(kù)數(shù)據(jù)類型詳解

    MySQL入門(二) 數(shù)據(jù)庫(kù)數(shù)據(jù)類型詳解

    這個(gè)數(shù)據(jù)庫(kù)所遇到的數(shù)據(jù)類型今天統(tǒng)統(tǒng)在這里講清楚了,以后在看到什么數(shù)據(jù)類型,咱度應(yīng)該認(rèn)識(shí),對(duì)我來(lái)說(shuō),最不熟悉的應(yīng)該就是時(shí)間類型這塊了。但是通過(guò)今天的學(xué)習(xí),已經(jīng)解惑了。下面就跟著我的節(jié)奏去把這個(gè)拿下吧
    2018-07-07
  • MySQL 線上日志庫(kù)遷移實(shí)例

    MySQL 線上日志庫(kù)遷移實(shí)例

    這篇文章主要介紹了MySQL 線上日志庫(kù)遷移實(shí)例,幫助大家更好的理解和學(xué)習(xí)使用MySQL,感興趣的朋友可以了解下
    2021-03-03
  • Mysql離線安裝8.0.26的圖文教程

    Mysql離線安裝8.0.26的圖文教程

    這篇文章主要介紹了Mysql離線安裝8.0.26的圖文教程,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-02-02
  • window10下mysql 8.0.20 安裝配置方法圖文教程

    window10下mysql 8.0.20 安裝配置方法圖文教程

    這篇文章主要為大家詳細(xì)介紹了window10下mysql 8.0.20 安裝配置方法圖文教程,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05

最新評(píng)論

静安区| 溆浦县| 栾川县| 沁阳市| 西乡县| 辛集市| 南汇区| 全椒县| 咸丰县| 梁平县| 桐庐县| 元江| 江城| 沙田区| 深州市| 邮箱| 新巴尔虎右旗| 新民市| 丁青县| 冕宁县| 山西省| 裕民县| 雅江县| 溧阳市| 灵石县| 仲巴县| 开阳县| 河北省| 上杭县| 六枝特区| 孙吴县| 承德市| 济宁市| 林芝县| 汤原县| 鲁山县| 兴文县| 金寨县| 光山县| 宝山区| 贵溪市|