count(*) count(1) count(字段)

【以下內容總結自丁奇老師的MySQL45講】
MyISAM引擎直接記錄了表的行數,所以會很快。
但是InnoDB不同。不存在這個字段,InnoDB 是索引組織表,主鍵索引樹的葉子節點是數據,而普通索引樹的葉子
節點是主鍵值。所以,普通索引樹比主鍵索引樹小很多。對於 count() 這樣的操作,遍歷哪個索引樹得到的結果邏輯上都是一樣的。因此,MySQL 優化器會找到最小的那棵樹來遍歷。在保證邏輯正確的前提下,儘量減少掃描的數據量,是數據庫系統設計的通用法則之一。
這裏,首先你要弄清楚 count() 的語義。count() 是一個聚合函數,對於返回的結果集,一行行地判斷,如果 count 函數的參數不是 NULL,累計值就加 1,否則不加。最後返回
累計值。
所以,count(
)、count(主鍵 id) 和 count(1) 都表示返回滿足條件的結果集的總行數;而
count(字段),則表示返回滿足條件的數據行裏面,參數“字段”不爲 NULL 的總個數。
至於分析性能差別的時候,你可以記住這麼幾個原則:

  1. server 層要什麼就給什麼;
  2. InnoDB 只給必要的值;
  3. 現在的優化器只優化了 count(*) 的語義爲“取行數”,其他“顯而易見”的優化並沒
    有做。
    這是什麼意思呢?接下來,我們就一個個地來看看。
    對於 count(主鍵 id) 來說,InnoDB 引擎會遍歷整張表,把每一行的 id 值都取出來,返
    回給 server 層。server 層拿到 id 後,判斷是不可能爲空的,就按行累加。
    對於 count(1) 來說,InnoDB 引擎遍歷整張表,但不取值。server 層對於返回的每一
    行,放一個數字“1”進去,判斷是不可能爲空的,按行累加。
    單看這兩個用法的差別的話,你能對比出來,count(1) 執行得要比 count(主鍵 id) 快。因
    爲從引擎返回 id 會涉及到解析數據行,以及拷貝字段值的操作。
    對於 count(字段) 來說:
    加微信 ixuexi66 獲取最新一手資源
  4. 如果這個“字段”是定義爲 not null 的話,一行行地從記錄裏面讀出這個字段,判斷不
    能爲 null,按行累加;
  5. 如果這個“字段”定義允許爲 null,那麼執行的時候,判斷到有可能是 null,還要把值
    取出來再判斷一下,不是 null 才累加。
    也就是前面的第一條原則,server 層要什麼字段,InnoDB 就返回什麼字段。
    但是 count() 是例外,並不會把全部字段取出來,而是專門做了優化,不取值。
    count(
    ) 肯定不是 null,按行累加。
    看到這裏,你一定會說,優化器就不能自己判斷一下嗎,主鍵 id 肯定非空啊,爲什麼不能
    按照 count() 來處理,多麼簡單的優化啊。
    當然,MySQL 專門針對這個語句進行優化,也不是不可以。但是這種需要專門優化的情
    況太多了,而且 MySQL 已經優化過 count(
    ) 了,你直接使用這種用法就可以了。
    所以結論是:按照效率排序的話,*count(字段)<count(主鍵 id)<count(1)≈count()*,所
    以我建議你,儘量使用 count(
    )。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章