InnoDB中的的聚合函式count(?)哪個效率高?
阿新 • • 發佈:2022-05-05
MyISAM 引擎把一個表的總行數存在了磁碟上,因此執行 count(*) 的時候會直接返回這個數,效率很高;
而 InnoDB 引擎就麻煩了,它執行 count(*) 的時候,需要把資料一行一行地從引擎裡面讀出來,然後累積計數。
count() 是一個聚合函式,對於返回的結果集,一行行地判斷,如果 count 函式的引數不是 NULL,累計值就加 1,否則不加。最後返回累計值。
所以,count(*)、count(主鍵 id) 和 count(1) 都表示返回滿足條件的結果集的總行數;而 count(欄位),則表示返回滿足條件的資料行裡面,引數“欄位”不為 NULL 的總個數。
對於 count(主鍵 id) 來說,InnoDB 引擎會遍歷整張表,把每一行的 id 值都取出來,返回給 server 層。server 層拿到 id 後,判斷是不可能為空的,就按行累加。
對於 count(1) 來說,InnoDB 引擎遍歷整張表,但不取值。server 層對於返回的每一行,放一個數字“1”進去,判斷是不可能為空的,按行累加。
單看這兩個用法的差別的話,你能對比出來,count(1) 執行得要比 count(主鍵 id) 快。因為從引擎返回 id 會涉及到解析資料行,以及拷貝欄位值的操作。
對於 count(欄位) 來說:
- 如果這個“欄位”是定義為 not null 的話,一行行地從記錄裡面讀出這個欄位,判斷不能為 null,按行累加;
- 如果這個“欄位”定義允許為 null,那麼執行的時候,判斷到有可能是 null,還要把值取出來再判斷一下,不是 null 才累加。
但是 count(*) 是例外,並不會把全部欄位取出來,而是專門做了優化,不取值。count(*) 肯定不是 null,按行累加。
所以結論是:
按照效率排序的話,count(欄位)<count(id)<count(*)≈count(1);
所以實際使用中如何不考慮某個欄位為空的情況,優先使用count(1)或者count(*);