MySQL學習筆記:count(1)、count(*)、count(字段)的區別

關於數據庫中行數統計,不管是MySQL仍是Oracle,都有一個函數可使用,那就是COUNT。面試

可是,就是這個經常使用的COUNT函數,卻暗藏着不少玄機,尤爲是在面試的時候,一不當心就會被虐。不信的話請嘗試回答下如下問題:數據庫

> 一、COUNT有幾種用法?
> 二、COUNT(字段名)和COUNT(*)的查詢結果有什麼不一樣?
> 三、COUNT(1)和COUNT(*)之間有什麼不一樣?
> 四、COUNT(1)和COUNT(*)之間的效率哪一個更高?
> 五、爲何《阿里巴巴Java開發手冊》建議使用COUNT(*)
> 六、MySQL的MyISAM引擎對COUNT(*)作了哪些優化?
> 七、MySQL的InnoDB引擎對COUNT(*)作了哪些優化?
> 八、上面提到的MySQL對COUNT(*)作的優化,有一個關鍵的前提是什麼?
> 九、SELECT COUNT(*) 的時候,加不加where條件有差異嗎?
> 十、COUNT(*)、COUNT(1)和COUNT(字段名)的執行過程是怎樣的?

以上10道題,若是能夠所有準確無誤的回答的話,那說明你真的很瞭解COUNT函數了。緩存

1.初識COUNT

一、COUNT(expr) ,返回SELECT語句檢索的行中expr的值不爲NULL的數量。結果是一個BIGINT值。併發

二、若是查詢結果沒有命中任何記錄,則返回0函數

三、可是,值得注意的是,COUNT(*) 的統計結果中,會包含值爲NULL的行數。性能

除了COUNT(id)COUNT(*)之外,還可使用COUNT(常量)(如COUNT(1))來統計行數,那麼這三條SQL語句有什麼區別呢?到底哪一種效率更高呢?爲何《阿里巴巴Java開發手冊》中強制要求不讓使用 COUNT(列名)COUNT(常量)來替代 COUNT(*)呢?優化

2.COUNT(字段)、COUNT(常量)和COUNT(*)之間的區別

COUNT(常量)COUNT(*) 表示的是直接查詢符合條件的數據庫表的行數。spa

COUNT(列名)表示的是查詢符合條件的列的值不爲NULL的行數。code

COUNT(*)是SQL92定義的標準統計行數的語法,由於是標準語法,因此MySQL數據庫進行過不少優化。orm

SQL92,是數據庫的一個ANSI/ISO標準。它定義了一種語言(SQL)以及數據庫的行爲(事務、隔離級別等)。

3.COUNT(*)的優化

MySQL主要使用2種執行引擎:

  • InnoDB引擎
  • MyISAM引擎

MyISAM不支持事務,MyISAM中的鎖是表級鎖;而InnoDB支持事務,而且支持行級鎖。

MyISAM

MyISAM作了一個簡單的優化,把表的總行數單獨記錄下來,若是執行count(*)時能夠直接返回,前提是不能有where條件。MyISAM是表級鎖,不會有併發的行操做,因此查到的結果是準確的。

InnoDB

InnoDB不能使用這種緩存操做,由於支持事務,大部分操做都是行級鎖,行可能被並行修改,那麼緩存記錄不許確。

可是,InnoDB仍是針對COUNT(*)語句作了些優化的。

經過低成本的索引進行掃表,而不關注表的具體內容。

InnoDB中索引分爲聚簇索引(主鍵索引)和非聚簇索引(非主鍵索引),聚簇索引的葉子節點中保存的是整行記錄,而非聚簇索引的葉子節點中保存的是該行記錄的主鍵的值。

MySQL會優先選擇最小的非聚簇索引來掃表。

優化的前提是查詢語句中不包含where條件和group by條件。

4.COUNT(*)和COUNT(1)

MySQL官方文檔這麼說:

InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.

因此,對於count(1)count(*),MySQL的優化是徹底同樣的,根本不存在誰更快!

但依舊建議使用count(*),由於這是SQL92定義的標準統計行數的語法。

5.COUNT(字段)

進行全表掃描,判斷指定字段的值是否爲NULL,不爲NULL則累加。

性能比count(1)count(*)慢。

6.總結

COUNT函數的用法,主要用於統計表行數。主要用法有COUNT(*)COUNT(字段)COUNT(1)

由於COUNT(*)是SQL92定義的標準統計行數的語法,因此MySQL對他進行了不少優化,MyISAM中會直接把表的總行數單獨記錄下來供COUNT(*)查詢,而InnoDB則會在掃表的時候選擇最小的索引來下降成本。固然,這些優化的前提都是沒有進行where和group的條件查詢。

在InnoDB中COUNT(*)COUNT(1)實現上沒有區別,並且效率同樣,可是COUNT(字段)須要進行字段的非NULL判斷,因此效率會低一些。

由於COUNT(*)是SQL92定義的標準統計行數的語法,而且效率高,因此請直接使用COUNT(*)查詢表的行數!

參考連接:MySQL的COUNT語句,居然都能被面試官虐的這麼慘!?

相關文章
相關標籤/搜索