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

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

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

前言

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

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) 速度更快。

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

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

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

一、先搞懂三個COUNT語法的語義

1. COUNT(*)

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

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

2. COUNT(id)

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

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

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

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

COUNT(login_ip)

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

風(fēng)險兩點:

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

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

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

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

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

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

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

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

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

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

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

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

四、無WHERE條件的特殊場景

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

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

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

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

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

額外拓展一個寫法:

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

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

不用盲目推崇COUNT(1)。

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

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

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

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

-- 標準寫法
SELECT COUNT(*) AS active_num FROM user_login_log WHERE `date` = CURDATE();

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

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

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

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

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

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

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

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

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

九、補充:MyISAM簡要區(qū)分(了解即可)

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

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

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

新項目基本不會使用MyISAM,僅作知識拓展。

十、全文總結(jié)

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

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

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

相關(guān)文章

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

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

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

    MySQL報錯1118,數(shù)據(jù)類型長度過長問題及解決

    在使用MySQL過程中,常見的一個問題是報錯1118,這通常發(fā)生在創(chuàng)建表時,錯誤提示為“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 解壓版安裝配置方法圖文教程

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

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

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

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

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

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

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

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

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

    MySQL 線上日志庫遷移實例

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

    Mysql離線安裝8.0.26的圖文教程

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

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

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

最新評論

彭州市| 万载县| 来安县| 许昌市| 辽中县| 河源市| 珲春市| 铁岭市| 水城县| 苏州市| 莫力| 桦川县| 会东县| 磐石市| 平遥县| 余姚市| 宝应县| 凌海市| 宁化县| 彝良县| 甘肃省| 皋兰县| 汕尾市| 丰县| 晋中市| 专栏| 长治市| 易门县| 南宁市| 华蓥市| 若尔盖县| 永靖县| 温泉县| 临泽县| 平昌县| 克东县| 嘉善县| 榕江县| 平舆县| 赤壁市| 营口市|