MySQL數(shù)據(jù)庫(kù)統(tǒng)計(jì)函數(shù)COUNT的使用及說(shuō)明
1. COUNT 函數(shù)的作用
數(shù)據(jù)庫(kù)系統(tǒng)中 COUNT(expr)
用于統(tǒng)計(jì)數(shù)據(jù)行數(shù),其主要作用為返回SELECT語(yǔ)句檢索的行中 expr 表達(dá)式的值不為 NULL 的行的數(shù)量,返回值是一個(gè) BIGINT 值,如果查詢結(jié)果沒(méi)有命中任何記錄則返回 0。
通常的使用方式主要有以下兩種:
- COUNT(column) 表示統(tǒng)計(jì)對(duì)應(yīng)列有值(不為空)的數(shù)據(jù)的行數(shù)
- COUNT(*) 表示統(tǒng)計(jì)結(jié)果集的總行數(shù)
2. COUNT(*) 與 COUNT(1) 與 COUNT(column)
COUNT(expr)
統(tǒng)計(jì)的是 expr 不為 NULL的行數(shù),而在COUNT(column)
、 COUNT(1)
和 COUNT(*)
三種用法中,expr 分別是列名
、 常量
和*
。
這三個(gè)條件中常量是一個(gè)固定值,肯定不為NULL。
*
可以理解為查詢整行,所以肯定也不為NULL,只有列名的查詢結(jié)果有可能是NULL。
故 COUNT(1) 和 COUNT(*) 可認(rèn)為是直接查詢符合條件的數(shù)據(jù)庫(kù)表的行數(shù),而COUNT(column)表示的是查詢符合條件的列的值不為NULL的行數(shù)。
- 對(duì)于COUNT(1)和COUNT(*),官方的說(shuō)法是在 InnoDB 引擎中二者完全一樣,不存在快慢區(qū)別
- COUNT(column)的查詢則比較簡(jiǎn)單粗暴,就是進(jìn)行全表掃描,然后判斷指定字段的值是不是為NULL,不為NULL則累加
相比 COUNT(*),COUNT(column) 多了一個(gè)判斷所查詢的字段是否為 NULL 的步驟,所以效率要比 COUNT(*) 低
3. MySQL 對(duì) COUNT 的優(yōu)化
這些優(yōu)化的前提都是查詢語(yǔ)句中不包含 WHERE 及 GROUP BY 限定條件
3.1 MyISAM 引擎優(yōu)化
MyISAM 引擎的鎖是表級(jí)鎖,同一張表上的操作都是串行完成,故MyISAM做了一個(gè)簡(jiǎn)單的優(yōu)化,就是把表的總行數(shù)單獨(dú)記錄下來(lái)。
使用 COUNT(*) 查詢表的總行數(shù)時(shí),直接返回這個(gè)記錄下來(lái)的數(shù)值就可以了,當(dāng)然前提是不能有where條件
MyISAM之所以可以把表的總行數(shù)記錄下來(lái)供COUNT(*)查詢使用,是因?yàn)?strong>MyISAM數(shù)據(jù)庫(kù)是表級(jí)鎖,不會(huì)有并發(fā)的數(shù)據(jù)庫(kù)行數(shù)修改,所以查詢得到的行數(shù)是準(zhǔn)確的
3.2 InnoDB 引擎優(yōu)化
因?yàn)?InnoDB 支持事務(wù),其中大部分操作都是行級(jí)鎖,所以表的行數(shù)可能會(huì)被并發(fā)修改,在這種情況下將總行數(shù)記錄下來(lái)的方式就不準(zhǔn)確了。
因此 InnoDB 中使用 COUNT( * ) 查詢行數(shù)的時(shí)候,不可避免地要進(jìn)行掃表,只能在掃表過(guò)程中來(lái)優(yōu)化效率
我們知道,InnoDB 中索引分為聚簇索引(主鍵索引)和非聚簇索引(非主鍵索引),聚簇索引的葉子節(jié)點(diǎn)中保存的是整行記錄,而非聚簇索引的葉子節(jié)點(diǎn)中保存的是該行記錄的主鍵的值。
COUNT(*)只是為了統(tǒng)計(jì)總行數(shù),不用關(guān)心查到的具體值,如果在掃表的過(guò)程中選擇一個(gè)成本較低的索引的話,那就可以大大節(jié)省時(shí)間。
顯而易見(jiàn),非聚簇索引要比聚簇索引小很多,所以 InnoDB 引擎會(huì)優(yōu)先選擇最小的非聚簇索引來(lái)掃表。
根據(jù)這個(gè)特性可知,建表的時(shí)候除了主鍵索引以外,創(chuàng)建一個(gè)非主鍵索引也很有必要
4. COUNT 查詢優(yōu)化
假設(shè)有一張表t_user,里面有大概5000條記錄,一個(gè)需求是統(tǒng)計(jì) id 大于 20 的用戶數(shù)量,以下兩種寫法效率大不相同
簡(jiǎn)單的條件查找,近乎掃描全表,表較小時(shí)效率很高,表數(shù)據(jù)較多就很耗時(shí)
SELECT count( * ) FROM t_user WHERE id > 20;
另一個(gè)思路是先統(tǒng)計(jì) id 小于 20 的記錄,再使用總的行數(shù)減去該值就得到了結(jié)果。
這是因?yàn)椴樵儍?yōu)化階段會(huì)把該類子查詢當(dāng)作常數(shù)處理,只需掃描 id < 20 的行,開(kāi)銷大幅減少
SELECT ( SELECT COUNT( * ) FROM t_user ) - count( * ) FROM t_user WHERE id < 20;
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
解決mysql與navicat建立連接出現(xiàn)1251錯(cuò)誤
在本篇文章里小編給大家整理了一篇關(guān)于mysql與navicat建立連接出現(xiàn)1251錯(cuò)誤怎么解決的技術(shù)文章,需要的朋友們參考下。2019-08-08MySQL 4.1/5.0/5.1/5.5/5.6各版本的主要區(qū)別整理
這篇文章主要介紹了MySQL 4.1/5.0/5.1/5.5/5.6各版本的主要區(qū)別整理,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-08-08mysql根據(jù)拼音字母查詢(簡(jiǎn)單易懂的字段拼音查詢)
MySQL在開(kāi)發(fā)中,我們經(jīng)常需要根據(jù)字段拼音查詢數(shù)據(jù)庫(kù)中的數(shù)據(jù),它支持多種查詢方式,包括根據(jù)拼音字母查詢,使用 Collation 可以方便地進(jìn)行簡(jiǎn)單的拼音查詢,而使用拼音索引可以大幅提高查詢性能,根據(jù)具體的需求和情況,我們可以選擇合適的方法來(lái)實(shí)現(xiàn)拼音查詢2023-10-10Centos7下安裝和配置MySQL5.7.20的詳細(xì)教程
這篇文章主要介紹了Linux(CentOS7)下安裝和配置MySQL5.7.20詳細(xì)教程,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià),需要的朋友可以參考下2020-05-05MySQL動(dòng)態(tài)創(chuàng)建表,數(shù)據(jù)分表的存儲(chǔ)過(guò)程
MySQL動(dòng)態(tài)創(chuàng)建表,數(shù)據(jù)分表的存儲(chǔ)過(guò)程,需要的朋友可以參考下。2011-08-08Mysql systemctl start mysqld報(bào)錯(cuò)的問(wèn)題解決
最近運(yùn)行Mysql發(fā)現(xiàn)報(bào)錯(cuò),本文就來(lái)介紹一下Mysql systemctl start mysqld報(bào)錯(cuò)的問(wèn)題解決,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06MySQL查看和修改字符編碼的實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇MySQL查看和修改字符編碼的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-11-11Mysql8報(bào)錯(cuò)this is incompatible with sql_mo
這篇文章主要介紹了Mysql8報(bào)錯(cuò)this is incompatible with sql_mode=only_full_group_by問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01