溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

select count(?) from t之間的性能有什么差別

發(fā)布時間:2021-06-21 16:33:12 來源:億速云 閱讀:145 作者:chen 欄目:web開發(fā)

這篇文章主要介紹“select count(?) from t之間的性能有什么差別”,在日常操作中,相信很多人在select count(?) from t之間的性能有什么差別問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”select count(?) from t之間的性能有什么差別”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

在開發(fā)中,我們一定經(jīng)常遇到需要統(tǒng)計表總記錄的時候,在 select count(?) from t 這樣的查詢語句里面,count(*)、count(主鍵  id)、count(字段) 和 count(1) 該怎么選擇呢?

阿里巴巴開發(fā)規(guī)約其中MySQL規(guī)約中,有4條都在規(guī)范count的用法,我們查看其中的一條:

【強制】不要使用count(列名)或count(常量)來替代count(*),  count(*)就是SQL92定義的標(biāo)準(zhǔn)統(tǒng)計行數(shù)的語法,跟數(shù)據(jù)庫無關(guān),跟NULL和非NULL無關(guān)。

說明:count(*)會統(tǒng)計值為NULL的行,而count(列名)不會統(tǒng)計此列為NULL值的行。

那么今天我們就來聊聊這幾種不同的統(tǒng)計方式是怎么實現(xiàn)的,他們之間的性能差別是什么。

count()函數(shù)

首先我們需要了解count() 的語義。

count()是一個聚合函數(shù),對于返回的結(jié)果集,一行行的判斷,如果count函數(shù)的參數(shù)不是null,累計值就加1,否則不加。最后返回累計值。如果沒有則返回0。

count(*)、count(主鍵 id) 和 count(1) 都表示返回滿足條件的結(jié)果集的總行數(shù);而  count(字段),則表示返回滿足條件的數(shù)據(jù)行里面,參數(shù)“字段”不為null的總個數(shù)。

接下來我們具體分析每種統(tǒng)計方式的性能差別。

count(*)

我們在分析一條SQL語句的實現(xiàn)時,一定不能脫離存儲引擎,在不同的MySQL存儲引擎中,count(*)有不同的實現(xiàn)。

  • MyISAM引擎把一個表的總行數(shù)存在了磁盤上,所以在執(zhí)行count(*)的時候直接返回磁盤上的這個數(shù)就可以,效率很高。

  • InnoDB引擎是需要一行一行地從引擎中讀出數(shù)據(jù)然后累計計數(shù)。

這個時候你是不是在想,MySQL建表時的存儲引擎已經(jīng)默認為InnoDB了,而且很多MySQL相關(guān)的書籍中也提到不是特別場景的必要,就使用InnoDB。

但是我們在使用count(*)做統(tǒng)計的時候隨著表記錄的增加效率會越來越慢,InnoDB怎么就不能跟MyISAM一樣也把總記錄數(shù)提前存儲起來呢?

這里主要的一個原因是InnoDB是支持事務(wù)的,由于MVCC的原因,InnoDB表在某個時刻應(yīng)該返回多少行是不確定的,它必須根據(jù)當(dāng)前的事務(wù)隔離級別判斷某一個記錄對于當(dāng)前事務(wù)是否可見。

雖然InnoDB是需要一行一行的統(tǒng)計,但是MySQL也是做了優(yōu)化的。通過前面索引文章介紹的知識我們了解到,InnoDB分為主鍵索引樹和普通索引樹,普通索引樹的葉子節(jié)點是主鍵值而不是行記錄。所以,普通索引樹要比主鍵索引樹小很多,所以count(*)在遍歷索引樹的時候會找最小的那棵樹來遍歷。

在保證邏輯正確的前提下,盡量減少掃描的數(shù)據(jù)量,是數(shù)據(jù)庫系統(tǒng)設(shè)計的通用法則之一。

count(*)也并不會把全部字段取出來,而是做了優(yōu)化,不取值。

count(*)的參數(shù)肯定不是null,按行累加之后返回結(jié)果。

count(主鍵 id)

count(主鍵 id)  ,InnoDB引擎會遍歷整張表,把每一行的id值取出來,傳給server層。server層拿到引擎給的id值后,判斷是不可能為空的,就按行累加。

count(1)

count(1),InnoDB引擎遍歷整張表,但是不取值。server層對于返回的每一行存放一個數(shù)字1,判斷是不可能為空過的,按行累加。

count(字段)

而對于count(字段)字段來說,我們需要分兩種情況分析參數(shù)字段。

如果這個參數(shù)字段是不允許為null(not null)的,那么InnoDB引擎則一行行地從記錄里面讀取這個字段,判斷不能為null,則按行累加。

如果這個參數(shù)字段是允許為null的,那么執(zhí)行的時候,判斷到可能是null的時候還要把值取出來再判斷一次,不是null才累加。

小結(jié)

count(字段)和count(主鍵 id)因為需要從引擎中返回值,會涉及到解析數(shù)據(jù)行以及拷貝字段的操作,性能上差于其他兩種。

而count(字段)還需要判斷字段參數(shù)是否為null,多了判斷的操作,性能上會差于count(主鍵 id)。

count(1)和count(*)都不會涉及到取值,性能上差別不大。

所以結(jié)論就是,按照查詢效率排名結(jié)果如下:

count(字段)<count(主鍵 id)<count(1)&asymp;count(*)。

按照開發(fā)規(guī)范,建議盡量使用count(*)。

到此,關(guān)于“select count(?) from t之間的性能有什么差別”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI