mysql下count(*)和count(1)的区别
2019獨角獸企業重金招聘Python工程師標準>>>
今天看公司項目發現了一個奇怪sql寫法
select count(8) from ....這也許是開發人員不小心或者是習慣把*寫成了8,當然這并不影響程序運行的結果。
由此引發了我想知道count(*)和count(1)的區別。
其實關于count(*)和count(1)性能的爭論文章特別多,這類文章都沒講到重點。
我覺得我今天說的這個答案算的上是很權威的,因為答案來自mysql官方文檔關于count函數的解釋。
現在我能找到的mysql最老的版本文檔是5.5 鏈接如下:
https://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html
關于 count(*)和count(1) 有這樣一段話:
InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.
就是說在 InnoDB 引擎下,這兩個其實沒有性能上的差異。
但是在MyISAM引擎是有差異的,原文是這樣說的:
For MyISAM tables, COUNT(*) is optimized to return very quickly if the SELECT retrieves from one table, no other columns are retrieved, and there is no WHERE clause. For example: This optimization only applies to MyISAM tables, because an exact row count is stored for this storage engine and can be accessed very quickly. COUNT(1) is only subject to the same optimization if the first column is defined as NOT NULL.
MyISAM引擎對count(*)進行了優化,可以快速得到結果. 但是如果使用count(1),那么如果當第一列的結果不為空的時候才有這種優化,所以在MyISAM引擎下 如果第一列為空的話count(1)的查詢效率是沒有count(*)高的。
接下來對mysql官方的文檔大致翻譯下:
COUNT(*)返回檢索到的行數的計數,不管它們是否包含空值。
對于InnoDB這樣的事務性存儲引擎,存儲準確的行數是不太現實的,因為多個事務可能同時發生,每個事務都有可能影響計數。 InnoDB不保留表中的行數,因為并發事務可能同時“看到”不同的行數。因此,SELECT COUNT(*)語句只計算當前事務可見的行。
為了處理SELECT COUNT(*)語句,InnoDB掃描表的索引,如果索引不是完全在緩沖池中,那么這將花費一些時間。為了更快地計數,創建一個計數器表,并讓應用程序根據它的插入和刪除來更新它。但是,當數千個并發事務同時啟動對同一個計數器表更新時,這種方法可能無法很好地維護。如果想要一個大致的結果,則使用SHOW TABLE STATUS。
InnoDB以同樣的方式處理SELECT COUNT(*)和SELECT COUNT(1)操作。沒有性能差異。 對于MyISAM表,如果使用SELECT從一個表中檢索,沒有檢索其他列,也沒有WHERE子句,那么COUNT(*)被優化為快速返回。例如:
mysql> SELECT COUNT(*) FROM student;這種優化只適用于MyISAM表,因為為這個存儲引擎存儲了準確的行數,并且可以非常快速地訪問。COUNT(1)只有在第一列被定義為NOT NULL時才進行相同的優化。
總結:
很明顯在進行統計的時候最好就是使用count(*),至少在5.5+的版本可以這樣做,不管是在InnoDB還是MyISAM都能達到最佳性能。
目前mysql官方最新的文檔版本是8.0,鏈接為:
https://dev.mysql.com/doc/refman/8.0/en/group-by-functions.html#function_count
這里我要插下嘴,在8.0版本的mysql,對于 count(*) 是做了額外的優化的, 優化內容大致是:
從MySQL 8.0.13開始,如果沒有額外的子句(如WHERE或GROUP BY),那么InnoDB表的tbl_name查詢性能中的SELECT COUNT(*)將針對單線程工作負載進行優化。除非索引或優化器提示指示優化器使用不同的索引,否則InnoDB進程通過遍歷最小的可用輔助索引來選擇COUNT(*)語句。如果不存在二級索引,InnoDB將通過掃描聚集索引來選擇COUNT(*)語句。
轉載于:https://my.oschina.net/110NotFound/blog/3032543
總結
以上是生活随笔為你收集整理的mysql下count(*)和count(1)的区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 9 CompletableFu
- 下一篇: Leetcode PHP题解--D25