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

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

1、COUNT函數

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

風塵博客

翻譯一下:mysql

  1. COUNT(expr) ,返回SELECT語句檢索的行中expr的值不爲NULL的數量,結果是一個BIGINT值。
  2. 若是查詢結果沒有命中任何記錄,則返回0
  3. COUNT(*) 的統計結果中,會包含值爲NULL的行數。

《阿里巴巴Java開發手冊》也有以下要求:git

風塵博客

2、COUNT(列名)COUNT(常量)COUNT(*)

前面咱們提到過COUNT(expr)用於作行數統計,那麼COUNT(列名)COUNT(常量)COUNT(*)這三種語法中,expr分別是列名、 常量 和 *github

2.1 COUNT(*)COUNT(常量)

在列名、常量和*這三個條件中,常量是一個固定值,確定不爲NULL*能夠理解爲查詢整行,因此確定也不爲NULL,那麼就只有列名的查詢結果多是NULLsql

因此, 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的優化是徹底同樣的,根本不存在誰比誰快!post

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(*) 簡述

3、總結

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

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

3.1 小建議

既然 count(*) 在查詢上依賴於全部的數據集,因此咱們在設計上也須要儘可能的規避全量 count

一般狀況咱們針對可預見count 查詢會作適當的緩存,能夠是 Redis,也能夠是獨立的 MySQL count 表。

3.2 技術交流

  1. 風塵博客
  2. 風塵博客-掘金
  3. 風塵博客-博客園
  4. Github
相關文章
相關標籤/搜索