你是一直認爲 count(1) 比 count(*) 效率高麼?

MySQL count(1) 真的比 count(*) 快麼? 反正同事們都是這麼說的,我也姑且以爲對吧,那麼沒有本身研究一下究竟?若是我告訴你他們同樣,你信麼?緩存

有 Where 條件的 count,會根據掃碼結果count 一下全部的行數,其性能更依賴於你的 Where 條件,因此文章咱們僅針對沒有 Where 的狀況進行說明。函數

MyISAM 引擎會把一個表的總行數記錄了下來,因此在執行 count(*) 的時候會直接返回數量,執行效率很高。在 MySQL 5.5 之後默認引擎切換爲 InnoDB,InnoDB 由於增長了版本控制(MVCC)的緣由,同時有多個事務訪問數據而且有更新操做的時候,每一個事務須要維護本身的可見性,那麼每一個事務查詢到的行數也是不一樣的,因此不能緩存具體的行數,他每次都須要 count 一下全部的行數。那麼 count(1) 和 count(*)有區別麼?性能

InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference. 這是官網的解釋,直接點擊閱讀原文查看官文,因此兩種實現其實同樣,那麼具體爲何同樣呢?優化

探究這個問題首先咱們須要理解 count 的含義,以下是官網給出的定義設計

Returns a count of the number of non-NULL values of expr in the rows retrieved by a SELECT statement. The result is a BIGINT value.版本控制

大體的解釋是返回 SELECT 語句檢索的行中 expr 的非 NULL 值的計數,到這裏咱們就明白了,首先它是一個聚合函數,而後對 SELECT 的結果集進行計數,可是須要參數不爲 NULL。那麼咱們繼續閱讀官網的內容:code

COUNT(*) is somewhat different in that it returns a count of the number of rows retrieved, whether or not they contain NULL values.orm

大體的內容是說,count(*) 不一樣,他不關心這個返回值是否爲空都會計算他的count,由於 count(1) 中的 1 是恆真表達式,那麼 count(*) 仍是 count(1) 都是對全部的結果集進行 count,因此他們本質上沒有什麼區別。索引

固然這個地方 InnoDB 自己也作了一些優化,它會使用最小的二級索引來進行 count 的查詢優化。若是沒有二級索引纔會選擇聚簇索引,這樣的設計單從 IO 的角度就節省了不少開銷。事務

到這裏咱們明白了 count(*) 和 count(1) 本質上面實際上是同樣的,那麼 count(column) 又是怎麼回事呢?

count(column) 也是會遍歷整張表,可是不一樣的是它會拿到 column 的值之後判斷是否爲空,而後再進行累加,那麼若是針對主鍵須要解析內容,若是是二級因此須要再次根據主鍵獲取內容,又是一次 IO 操做,因此 count(column) 的性能確定不如前二者嘍,若是按照效率比較的話:count(*)=count(1)>count(primary key)>count(column)

既然 count(*) 在查詢上依賴於全部的數據集,是否是咱們在設計上也須要儘可能的規避全量 count 呢?一般狀況咱們針對可預見的 count 查詢會作適當的緩存,能夠是 Redis,也能夠是獨立的 MySQL count 表,固然不管是哪一種方式咱們都須要考慮一致性的問題。

相關文章
相關標籤/搜索