count(1)比count(*)效率高?


SELECT COUNT(*) FROM table_name是個再常見不過的統計需求了。
本文帶你了解下MysqlCOUNT函數。

一、COUNT函數

關於COUNT函數,在MySQL官網中有詳細介紹

風塵博客

翻譯一下:

  1. COUNT(expr) ,返回SELECT語句檢索的行中expr的值不為NULL的數量,結果是一個BIGINT值。
  2. 如果查詢結果沒有命中任何記錄,則返回0
  3. 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(常量),對於這二者到底有沒有區別:

  1. 有的說COUNT(*)執行時會轉換成COUNT(1),所以COUNT(1)少了轉換步驟,所以更快。
  2. 還有的說,因為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對其進行了很多優化:

  1. MyISAM中會直接把表的總行數單獨記錄下來供COUNT(*)查詢
  2. InnoDB會在掃表的時候選擇最小的索引來降低成本。

這些優化的前提都是沒有進行wheregroup的條件查詢,更多請參考MySQL 全表 COUNT(*) 簡述

三、總結

COUNT函數用於統計表行數,按照效率比較的話:

count(*)=count(常量)>count(列名)

3.1 小建議

既然 count(*) 在查詢上依賴於所有的數據集,所以我們在設計上也需要盡量的規避全量 count

通常情況我們針對可預見count 查詢會做適當的緩存,可以是 Redis,也可以是獨立的 MySQL count 表。

3.2 技術交流

  1. 風塵博客
  2. 風塵博客-掘金
  3. 風塵博客-博客園
  4. Github


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM