對於SQL中COUNT(1)和COUNT(*)執行效率上的誤解
轉自:http://blog.itpub.net/26736162/viewspace-2136339/
如題,SQL中COUNT(1)和COUNT(*)執行效率的高低,說法不一。不過本人認為二者執行效率是一樣的。
本文作如下闡述:
1、COUNT( )函式是資料庫(Oracle、MySQL等)中的聚合函式,用於統計結果集的行數。其語法形式如下所示:
COUNT({ * | [ DISTINCT | ALL ] expr }) [ OVER (analytic_clause) ]
可以把COUNT的使用情況分為以下3類:
(1)、COUNT(1)、COUNT(*)、COUNT(常量)、COUNT(主鍵)、COUNT(ROWID)、COUNT(非空列);
(2)、COUNT(允許為空列);
(3)、COUNT(DISTINCT 列名)。
2、下面分別從查詢結果和效率方面做比較:
(1)、結果區別a、COUNT(1)、COUNT(*)、COUNT(ROWID)、COUNT(常量)、COUNT(主鍵)、COUNT(非空列)
這幾種方式統計的行數是表中所有存在的行的總數,包括值為NULL的行和非空行。所以,這幾種方式的
執行結果相同。這裡的常量可以為數字或字串,
例如,COUNT(2)、COUNT(333)、COUNT('x')、COUNT('xiaomaimiao')。
注:這裡的COUNT(1)中的“1”並不表示表中的第一列,
b、COUNT(允許為空列) 這種方式統計的行數不會包括欄位值為NULL的行。
c、COUNT(DISTINCT 列名) 得到的結果是除去值為NULL和重複資料後的結果。
d、“SELECT COUNT(''),COUNT(NULL) FROM TEMP;”返回0行。
(2)、效率、索引
a、如果存在主鍵或非空列上的索引,那麼COUNT(1)、COUNT(*)、COUNT(ROWID)、COUNT(常量)、
COUNT(主鍵)、COUNT(非空列)會首先選擇主鍵上的索引快速全掃描(INDEX FAST FULL SCAN)。
若主鍵不存在則會選擇非空列上的索引。
若非空列上沒有索引則肯定走全表掃描(TABLE ACCESS FULL)。
其中,COUNT(ROWID)在走索引的時候比其它幾種方式要慢。通過10053事件可以看到這幾種方式除了
COUNT(ROWID)之外,其它最終都會轉換成COUNT(*)的方式來執行。
b、對於COUNT(COL1)來說,只要列欄位上有索引則會選擇索引快速全掃描(INDEX FAST FULL SCAN)。
而對於“SELECT COL1”來說,除非列上有NOT NULL約束,否則執行計劃會選擇全表掃描。
c、COUNT(DISTINCT 列名) 若列上有索引,且有非空約束或在WHERE子句中使用IS NOT NULL,
則會選擇索引快速全掃描。其餘情況選擇全表掃描。