1. 程式人生 > >對於SQL中COUNT(1)和COUNT(*)執行效率上的誤解

對於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,

    則會選擇索引快速全掃描。其餘情況選擇全表掃描。