SELECT COUNT(*) FROM table_name是個再常見不過的統計需求了,
本文帶你了解下Mysql的COUNT函式,
一、COUNT函式
關于COUNT函式,在MySQL官網中有詳細介紹:
翻譯一下:
COUNT(expr),回傳SELECT陳述句檢索的行中expr的值不為NULL的數量,結果是一個BIGINT值,- 如果查詢結果沒有命中任何記錄,則回傳
0 COUNT(*)的統計結果中,會包含值為NULL的行數,
在《阿里巴巴Java開發手冊》也有如下要求:
二、COUNT(列名)、COUNT(常量)和COUNT(*)
前面我們提到過
COUNT(expr)用于做行數統計,那么COUNT(列名)、COUNT(常量)和COUNT(*)這三種語法中,expr分別是列名、 常量 和*,
2.1 COUNT(*)和COUNT(常量)
在列名、常量和 *這三個條件中,常量是一個固定值,肯定不為NULL,*可以理解為查詢整行,所以肯定也不為NULL,那么就只有列名的查詢結果可能是NULL,
所以, COUNT(常量) 和 COUNT(*)表示的是直接查詢符合條件的資料庫表的行數,而COUNT(列名)表示的是查詢符合條件的列的值不為NULL的行數,
2.2 COUNT(*)和COUNT(1)區別
COUNT(1)就是COUNT(常量),對于這二者到底有沒有區別:
- 有的說
COUNT(*)執行時會轉換成COUNT(1),所以COUNT(1)少了轉換步驟,所以更快, - 還有的說,因為
MySQL針對COUNT(*)做了特殊優化,所以COUNT(*)更快,
到底哪種說法是對的?看下MySQL官方檔案:
InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.
通過檔案,對于COUNT(1)和COUNT(*),MySQL的優化是完全一樣的,根本不存在誰比誰快!
2.3 COUNT(列名)
相較于前兩者,COUNT(列名)的查詢就比較簡單粗暴了,就是進行全表掃描,然后判斷指定欄位的值是不是為NULL,不為NULL則累加,
相比
COUNT(*),COUNT(列名)多了一個步驟就是判斷所查詢的欄位是否為NULL,所以他的性能要比COUNT(*)慢,
here和group的條件查詢,
2.4 SQL92
除了查詢得到結果集有區別之外,COUNT(*)相比COUNT(常量) 和 COUNT(列名)來講,COUNT(*)是SQL92定義的標準統計行數的語法,因為他是標準語法,所以MySQL資料庫對他進行過很多優化,
SQL92,是資料庫的一個ANSI/ISO標準,它定義了一種語言(SQL)以及資料庫的行為(事務、隔離級別等),
2.5 COUNT(*)優化
因為COUNT(*)是SQL92定義的標準統計行數的語法,所以MySQL對其進行了很多優化:
MyISAM中會直接把表的總行數單獨記錄下來供COUNT(*)查詢InnoDB會在掃表的時候選擇最小的索引來降低成本,
這些優化的前提都是沒有進行
where和group的條件查詢,更多請參考MySQL 全表 COUNT(*) 簡述
三、總結
COUNT函式用于統計表行數,按照效率比較的話:
count(*)=count(常量)>count(列名)
3.1 小建議
既然 count(*) 在查詢上依賴于所有的資料集,所以我們在設計上也需要盡量的規避全量 count,
通常情況我們針對可預見的 count 查詢會做適當的快取,可以是 Redis,也可以是獨立的 MySQL count 表,
3.2 技術交流
- 風塵博客
- 風塵博客-掘金
- 風塵博客-博客園
- Github
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/82536.html
標籤:MySQL
上一篇:mysql必知必會--聯 結 表
