2009-08-03 50 views
582

想知道你們中的任何一個人是否使用Count(1)而不是Count(*),並且如果在性能上有明顯差異,或者這只是從過去的日子中提出的遺留習慣?計數(*)和計數(1)

(具體的數據庫是SQL Server 2005中)

+6

不知道SQL Server,但在MySQL是沒有區別的。另一方面COUNT(列)不同 – Greg 2009-08-03 10:19:00

+102

不正確。 COUNT(SomeColumn)將僅返回包含SomeColumn的非空值的行數。 COUNT(*)和COUNT('Foo')將返回表中的總行數。 – 2009-08-03 13:51:14

+1

進一步的細節檢查這個 [select count 1 vs select count * with detail detail](http://advancesharp.com/Questions/160/sql-server---select-count1-vs-select-count) – 2012-05-26 09:13:17

回答

491

沒有區別。

原因:

Books on-line說: 「COUNT ({ [ [ ALL | DISTINCT ] expression ] | * })

「1」 是一個非空表達式:所以這是一樣的COUNT(*)。 優化器可以識別它是什麼:微不足道的。

同爲EXISTS (SELECT * ...EXISTS (SELECT 1 ...

例子:

SELECT COUNT(1) FROM dbo.tab800krows 
SELECT COUNT(1),FKID FROM dbo.tab800krows GROUP BY FKID 

SELECT COUNT(*) FROM dbo.tab800krows 
SELECT COUNT(*),FKID FROM dbo.tab800krows GROUP BY FKID 

同一個IO,同樣的計劃,工程

編輯,2011

Similar question on DBA.SE譯者:

編輯,2011年12月

COUNT(*)ANSI-92特別提到(尋找 「Scalar expressions 125」)

案例:

一)如果指定COUNT(*),那麼結果是T的基數。

也就是說,ANSI標準將其識別爲出血o明白你的意思。 COUNT(1)已被RDBMS供應商優化,因爲這個迷信的。否則就按照ANSI

b)否則進行評價,讓TX是單柱表,它是將所述<值表達式>至T 的每一行,消除空值的 結果。如果一個或多個空值 淘汰,那麼完成狀態:警告 -

12

我期望的優化器,以確保有怪異的外邊緣的情況下沒有真正的區別。

與任何事情一樣,唯一真正的方法是測量您的具體案例。

這就是說,我一直使用COUNT(*)

62

在SQL Server中,這些語句產生相同的計劃。

與流行的觀點相反,在甲骨文他們也是如此。在Oracle中是相當計算密集型的功能。

在我的測試數據庫,t_even1,000,000

這個查詢表:

運行的48秒,因爲函數需要評估每個SYS_GUID()返回,以確保它不是一個NULL

然而,這個查詢:

SELECT COUNT(*) 
FROM (
     SELECT SYS_GUID() 
     FROM t_even 
     ) 

運行的,但2秒,因爲它doen't甚至試圖評估SYS_GUID()(儘管*是參數COUNT(*)

43

顯然,COUNT(*)和COUNT(1)將總是返回相同的結果。因此,如果其中一個比另一個慢,這實際上是由於優化器錯誤。由於這兩種形式在查詢中都非常頻繁地使用,因此數據庫管理系統允許這樣的錯誤保持不固定是沒有意義的。因此,您會發現兩種表單的性能在所有主要的SQL DBMS中可能都是相同的。

15

COUNT(*)COUNT(1)在結果和性能的情況下是相同的。

7
SET STATISTICS TIME ON 

select count(1) from MyTable (nolock) -- table containing 1 million records. 

SQL Server的執行時間:
CPU時間= 31毫秒,經過的時間= 36毫秒。

select count(*) from MyTable (nolock) -- table containing 1 million records. 

SQL Server的執行時間:
CPU時間= 46毫秒,經過時間= 37毫秒。

我已經跑了這個數百次,每次都清除緩存。結果因服務器負載不同而不時變化,但幾乎總是計數(*)的CPU時間更高。

17

在SQL-92標準中,COUNT(*)具體表示「表達式的基數」(可以是基表,VIEW,派生表,CTE等)。

我想這個想法是COUNT(*)很容易解析。使用任何其他表達式都需要解析器確保它不引用任何列(COUNT('a'),其中a是文字,而COUNT(a)其中a是列可以產生不同的結果)。

同樣,COUNT(*)可以很容易地被熟悉SQL標準的人類編碼器挑選出來,這是處理多個供應商的SQL產品時的一項有用技能。

此外,在特殊情況下SELECT COUNT(*) FROM MyPersistedTable;,這個想法是DBMS可能會持有表的基數的統計數據。

因此,因爲COUNT(1)COUNT(*)在語義上是等價的,所以我使用COUNT(*)

6

由於這個問題一再出現,這裏還有一個答案。我希望在這裏爲想要了解「最佳實踐」的初學者添加一些內容。

SELECT COUNT(*) FROM something計數記錄這是一件容易的事。

SELECT COUNT(1) FROM something檢索每個記錄1並比計數非空的1,這實質上是計數記錄,只是更復雜。

話雖如此:好的dbms注意到第二個陳述會導致與第一個陳述相同的計數,並相應地重新解釋它,因爲不做不必要的工作。所以通常這兩種表述都會導致相同的執行計劃並且花費相同的時間。

但是從可讀性的角度來看,您應該使用第一條語句。你想計數記錄,所以計數記錄,而不是表達式。僅當您想計算某些事情的非空發生時才使用COUNT(表達式)。

6

我在8 GB RAM hyper-v盒子上對SQL Server 2012進行了快速測試。你可以看到自己的結果。在運行這些測試時,除SQL Server Management Studio外,我沒有運行任何其他窗口應用程序。

我的表模式:

CREATE TABLE [dbo].[employee](
    [Id] [bigint] IDENTITY(1,1) NOT NULL, 
    [Name] [nvarchar](50) NOT NULL, 
CONSTRAINT [PK_employee] PRIMARY KEY CLUSTERED 
(
    [Id] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 

Employee表記錄總數:178090131(〜1.78億行)

首先查詢:

Set Statistics Time On 
Go  
Select Count(*) From Employee 
Go  
Set Statistics Time Off 
Go 

結果第一個查詢:

SQL Server parse and compile time: 
CPU time = 0 ms, elapsed time = 35 ms. 

(1 row(s) affected) 

SQL Server Execution Times: 
    CPU time = 10766 ms, elapsed time = 70265 ms. 
SQL Server parse and compile time: 
    CPU time = 0 ms, elapsed time = 0 ms. 

第二查詢:

Set Statistics Time On 
    Go  
    Select Count(1) From Employee 
    Go  
    Set Statistics Time Off 
    Go 

第二查詢的結果:

SQL Server parse and compile time: 
    CPU time = 14 ms, elapsed time = 14 ms. 

(1 row(s) affected) 

SQL Server Execution Times: 
    CPU time = 11031 ms, elapsed time = 70182 ms. 
SQL Server parse and compile time: 
    CPU time = 0 ms, elapsed time = 0 ms. 

您可以注意到有83的差(= 70265 - 70182)毫秒,其在查詢運行時可以很容易地歸因於確切的系統條件。此外,我也做了一次運行,所以如果我做幾次運行並做一些平均操作,這種差異會變得更加準確。如果對於這樣一個巨大的數據集來說,差異小於100毫秒,那麼我們可以輕鬆得出結論:這兩個查詢沒有任何性能差異,這是由SQL Server引擎展現的。

注意:在兩次運行中,RAM的命中率接近100%。在啓動兩個運行之前,我重新啓動了SQL Server服務。

-1

輕鬆演示COUNT(*)比COUNT(<部分彩色>) -

USE tempdb; 
GO 

IF OBJECT_ID(N'dbo.Blitzen', N'U') IS NOT NULL DROP TABLE dbo.Blitzen; 
GO 

CREATE TABLE dbo.Blitzen (ID INT NULL, Somelala CHAR(1) NULL); 

INSERT dbo.Blitzen SELECT 1, 'A'; 
INSERT dbo.Blitzen SELECT NULL, NULL; 
INSERT dbo.Blitzen SELECT NULL, 'A'; 
INSERT dbo.Blitzen SELECT 1, NULL; 

SELECT COUNT(*), COUNT(1), COUNT(ID), COUNT(Somelala) FROM dbo.Blitzen; 
GO 

DROP TABLE dbo.Blitzen; 
GO