count查詢優化


  這里討論的count查詢優化是針對INNODB存儲引擎的!

  首先拋出一個問題

  count(*)、count(主鍵)、count(1)、count(字段)它們四者之間的效率如何排序?

  在我們以往的工作經驗中,總是聽到說不要使用count(*),因為 * 號代表了所有列,計算會更慢,然后就推薦了使用count(主鍵)。但事實真的是這樣嗎?

筆者在最近的學習中也才認識到這個錯誤。

  這四者正確的排序應該是這樣的:

count(1) > count(*) > count(主鍵) > count(字段)

  筆者特意在一張只有主鍵索引的1千萬條數據的表中做了測試,以下是測試的結果:

       

 

   這張圖的數據不是偶然的,筆者針對每種查詢執行了多次,結果不會有太大的變化,驗證了以上排序的正確性。

  count()的作用

  count()是一個特殊的函數,有兩種非常不同的作用:它可以統計某個列值的數量,也可以統計行數。在統計列值時要求列值

是非空的(不統計NULL)。如果在count()的括號中指定了列或者列的表達式,則統計的就是這個表達式有值的結果數,而不是NULL。

  count()的另一個作用是統計結果集的行數。當MYSQL確認括號內的表達式值不可能為空時,實際上就是在統計行數。最簡單的就

是當我們使用count(*)的時候,這種情況下通配符 * 並不會像我們猜想的那樣擴展成所有的列,實際上,它會忽略所有的列而直接統計

所有的行數。

  最常見的一個錯誤就是,在括號內指定了一個列卻希望統計結果集的行數。如果希望知道的是結果集的行數,最好使用COUNT(*),

這樣寫意義清晰,性能也會很好。

  count()的另一個優化

  業務代碼中,有這樣一個需求,需要根據一個或多個條件,查詢是否存在記錄,不關心有多少條記錄。普遍的SQL及代碼寫法如下:

SELECT count(*) FROM T WHERE a = 1 AND b = 2

  java寫法如下

Integer exist = xxDao.existXxxxByXxx(params);
if ( exist != NULL ) {
  //當存在時,執行這里的代碼
} else {
  //當不存在時,執行這里的代碼
}

  對於此處的select count(*),並不需求將符合條件的條數都統計出來,可以優化成如下的SQL:

SELECT count(*) FROM T WHERE a = 1 AND b = 2 LIMIT 1

  這里相比上面的SQL多了LIMIT關鍵字,在MYSQL中,執行器執行到LIMIT關鍵字,只要滿足LIMIT的條數,存儲引擎就不會再對數據文件

進行檢索,直接返回,所以這里只需要檢索到1條之后就返回結果,效率可想而知快了不少!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM