關(guān)于sql?count(列名)、count(常量)、count(*)之間的區(qū)別
COUNT(列名)、COUNT(常量)和COUNT(*)之間的區(qū)別
COUNT( * )和COUNT(1) :在InnoDB中COUNT(*)和COUNT(1)實現(xiàn)上沒有區(qū)別,而且效率一樣,統(tǒng)計結(jié)果中,會包含值為NULL的行數(shù)COUNT(字段): 需要進(jìn)行字段的非NULL判斷,所以效率會低一些。
因為COUNT( * )是SQL92定義的標(biāo)準(zhǔn)統(tǒng)計行數(shù)的語法,并且效率高,所以沒有某個字段不為null 的統(tǒng)計行數(shù)需求請直接使用COUNT( * )查詢表的行數(shù)!
COUNT(id)和COUNT()以外,還可以使用COUNT(常量)(如COUNT(1))來統(tǒng)計行數(shù),那么這三條SQL語句有什么區(qū)別呢?
到底哪種效率更高呢?
為什么《阿里巴巴Java開發(fā)手冊》中強制要求不讓使用 COUNT(列名)或 COUNT(常量)來替代 COUNT()呢?
1、COUNT(列名) ,返回SELECT語句檢索的行中expr的值不為NULL的數(shù)量。結(jié)果是一個BIGINT值。
2、但是,值得注意的是,COUNT( * ) 和count(1)的統(tǒng)計結(jié)果中,會包含值為NULL的行數(shù)。
那么列名、 常量 和 *這三個條件中,常量 是一個固定值,肯定不為NULL。*可以理解為查詢整行,所以肯定也不為NULL,那么就只有列名的查詢結(jié)果有可能是NULL了。
所以, COUNT(常量) 和 COUNT( * )表示的是直接查詢符合條件的數(shù)據(jù)庫表的行數(shù)。而COUNT(列名)表示的是查詢符合條件的列的值不為NULL的行數(shù)。
COUNT(*)是SQL92定義的標(biāo)準(zhǔn)統(tǒng)計行數(shù)的語法,因為他是標(biāo)準(zhǔn)語法,所以MySQL數(shù)據(jù)庫對他進(jìn)行過很多優(yōu)化。
COUNT(*)和COUNT(1)
COUNT(*)和COUNT(1)這二者到底有沒有區(qū)別,網(wǎng)上的說法眾說紛紜。
有的說COUNT(*)執(zhí)行時會轉(zhuǎn)換成COUNT(1),所以COUNT(1)少了轉(zhuǎn)換步驟,所以更快。
還有的說,因為MySQL針對COUNT()做了特殊優(yōu)化,所以COUNT()更快。
那么,到底哪種說法是對的呢?
看下MySQL官方文檔是怎么說的:
InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.
畫重點:
same way , no performance difference。
所以,對于COUNT(1)和COUNT(*),MySQL的優(yōu)化是完全一樣的,根本不存在誰比誰快!
COUNT( * )和COUNT(字段)
COUNT(字段),他的查詢就比較簡單粗暴了,就是進(jìn)行全表掃描,然后判斷指定字段的值是不是為NULL,不為NULL則累加。
相比COUNT(),COUNT(字段)多了一個步驟就是判斷所查詢的字段是否為NULL,所以他的性能要比COUNT()慢。
COUNT(*)的優(yōu)化
MySQL中比較常用的執(zhí)行引擎就是InnoDB和MyISAM。
MyISAM
不包含WHERE或GROUP BY等條件
MyISAM不支持事務(wù),MyISAM中的鎖是表級鎖;而InnoDB支持事務(wù),并且支持行級鎖。
因為MyISAM的鎖是表級鎖,所以同一張表上面的操作需要串行進(jìn)行,所以,MyISAM做了一個簡單的優(yōu)化,那就是它可以把表的總行數(shù)單獨記錄下來,如果從一張表中使用COUNT(*)進(jìn)行查詢的時候,可以直接返回這個記錄下來的數(shù)值就可以了,當(dāng)然,前提是不能有where條件。
MyISAM之所以可以把表中的總行數(shù)記錄下來供COUNT(*)查詢使用,那是因為MyISAM數(shù)據(jù)庫是表級鎖,不會有并發(fā)的數(shù)據(jù)庫行數(shù)修改,所以查詢得到的行數(shù)是準(zhǔn)確的。
InnoDB
不包含WHERE或GROUP BY等條件
InnoDB來說,就不能做這種緩存操作了,因為InnoDB支持事務(wù),其中大部分操作都是行級鎖,所以可能表的行數(shù)可能會被并發(fā)修改,那么緩存記錄下來的總行數(shù)就不準(zhǔn)確了。
InnoDB中索引分為主鍵索引和非主鍵索引主鍵引的葉子節(jié)點中保存的是整行記錄,而非主鍵索引的葉子節(jié)點中保存的是該行記錄的主鍵的值。
所以,相比之下,非主鍵索引要比主鍵索引小很多,所以MySQL會優(yōu)先選擇最小的非主鍵索引來掃表。所以,當(dāng)我們建表的時候,除了主鍵索引以外,創(chuàng)建一個非主鍵索引還是有必要的。
count(*)、count(列名)、count(常量)的理解
內(nèi)容來之阿里巴巴的開發(fā)手冊:
1. 【強制】不要使用 count(列名)或 count(常量)來替代 count(*),count(*)是 SQL92 定義的
標(biāo)準(zhǔn)統(tǒng)計行數(shù)的語法,跟數(shù)據(jù)庫無關(guān),跟 NULL 和非 NULL 無關(guān)。
說明:count(*)會統(tǒng)計值為 NULL 的行,而 count(列名)不會統(tǒng)計此列為 NULL 值的行。
2. 【強制】count(distinct col) 計算該列除 NULL 之外的不重復(fù)行數(shù),注意 count(distinct col1, col2) 如果其中一列全為 NULL,那么即使另一列有不同的值,也返回為 0。
3. 【強制】當(dāng)某一列的值全是 NULL 時,count(col)的返回結(jié)果為 0,但 sum(col)的返回結(jié)果 為 NULL,因此使用 sum()時需注意 NPE 問題。
正例:使用如下方式來避免 sum 的 NPE 問題:SELECT IFNULL(SUM(column), 0) FROM table;
4. 【強制】使用 ISNULL()來判斷是否為 NULL 值。
說明:NULL 與任何值的直接比較都為 NULL。
1) NULL<>NULL 的返回結(jié)果是 NULL,而不是 false。
2) NULL=NULL 的返回結(jié)果是 NULL,而不是 true。
3) NULL<>1 的返回結(jié)果是 NULL,而不是 true。
如何在同一個查詢中統(tǒng)計同,一個列的不同值的數(shù)量,以減少查詢的語句量。
例如:
通過一個查詢返回各種不同顏色的商品數(shù)量 。
select count(color='blue' or color='red') from items; (不滿足條件,因為無法區(qū)分不同顏色的商品數(shù)量) select count(*) from items where color = 'blue' and color = 'red';(不滿足條件,顏色的條件是互斥的)
下面為滿足條件的例子:
select sum(if(color = 'blue', 1, 0)) as blue, sum(if(color = 'red', 1, 0)) as red from items; select count(color = 'blue' or NULL) as blue, count(color = 'red' or NULL) as red from items;
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
MySQL中CONCAT和GROUP_CONCAT方法的區(qū)別詳解
本文主要介紹了MySQL中CONCAT和GROUP_CONCAT方法的區(qū)別詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01分組查詢GROUP BY的使用與SQL執(zhí)行順序的講解
今天小編就為大家分享一篇關(guān)于分組查詢GROUP BY的使用與SQL執(zhí)行順序的講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-03MySQL遠(yuǎn)程連接丟失問題解決方法(Lost connection to MySQL server)
這篇文章主要介紹了MySQL遠(yuǎn)程連接丟失問題解決方法,Mysql錯誤Lost connection to MySQL server at ‘reading initial communication packet’, system error: 0解決方法,需要的朋友可以參考下2014-06-06windows 64位下MySQL 8.0.15安裝教程圖文詳解
本文通過圖文并茂的形式給大家介紹了MySQL 8.0.15安裝教程(windows 64位),非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-04-04Mysql如何通過binlog日志恢復(fù)數(shù)據(jù)詳解
binlog日志用于記錄所有更新了數(shù)據(jù)或者已經(jīng)潛在更新了數(shù)據(jù)的所有語句,下面這篇文章主要給大家介紹了關(guān)于Mysql如何通過binlog日志恢復(fù)數(shù)據(jù)的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-02-02Mysql中between...and引起的索引失效問題及解決
這篇文章主要介紹了Mysql中between...and引起的索引失效問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07