想知道你們中的任何一個人是否使用Count(1)
而不是Count(*)
,並且如果在性能上有明顯差異,或者這只是從過去的日子中提出的遺留習慣?計數(*)和計數(1)
(具體的數據庫是SQL Server 2005中)
想知道你們中的任何一個人是否使用Count(1)
而不是Count(*)
,並且如果在性能上有明顯差異,或者這只是從過去的日子中提出的遺留習慣?計數(*)和計數(1)
(具體的數據庫是SQL Server 2005中)
沒有區別。
原因:
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
編輯,2011年12月
COUNT(*)
在ANSI-92特別提到(尋找 「Scalar expressions 125
」)
案例:
一)如果指定COUNT(*),那麼結果是T的基數。
也就是說,ANSI標準將其識別爲出血o明白你的意思。 COUNT(1)
已被RDBMS供應商優化,因爲這個迷信的。否則就按照ANSI
b)否則進行評價,讓TX是單柱表,它是將所述<值表達式>至T 的每一行,消除空值的 結果。如果一個或多個空值 淘汰,那麼完成狀態:警告 -
我期望的優化器,以確保有怪異的外邊緣的情況下沒有真正的區別。
與任何事情一樣,唯一真正的方法是測量您的具體案例。
這就是說,我一直使用COUNT(*)
。
在SQL Server中,這些語句產生相同的計劃。
與流行的觀點相反,在甲骨文他們也是如此。在Oracle中是相當計算密集型的功能。
在我的測試數據庫,t_even
是1,000,000
行
這個查詢表:
運行的48
秒,因爲函數需要評估每個SYS_GUID()
返回,以確保它不是一個NULL
。
然而,這個查詢:
SELECT COUNT(*)
FROM (
SELECT SYS_GUID()
FROM t_even
)
運行的,但2
秒,因爲它doen't甚至試圖評估SYS_GUID()
(儘管*
是參數COUNT(*)
)
顯然,COUNT(*)和COUNT(1)將總是返回相同的結果。因此,如果其中一個比另一個慢,這實際上是由於優化器錯誤。由於這兩種形式在查詢中都非常頻繁地使用,因此數據庫管理系統允許這樣的錯誤保持不固定是沒有意義的。因此,您會發現兩種表單的性能在所有主要的SQL DBMS中可能都是相同的。
COUNT(*)
和COUNT(1)
在結果和性能的情況下是相同的。
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時間更高。
在SQL-92標準中,COUNT(*)
具體表示「表達式的基數」(可以是基表,VIEW,派生表,CTE等)。
我想這個想法是COUNT(*)
很容易解析。使用任何其他表達式都需要解析器確保它不引用任何列(COUNT('a')
,其中a
是文字,而COUNT(a)
其中a
是列可以產生不同的結果)。
同樣,COUNT(*)
可以很容易地被熟悉SQL標準的人類編碼器挑選出來,這是處理多個供應商的SQL產品時的一項有用技能。
此外,在特殊情況下SELECT COUNT(*) FROM MyPersistedTable;
,這個想法是DBMS可能會持有表的基數的統計數據。
因此,因爲COUNT(1)
和COUNT(*)
在語義上是等價的,所以我使用COUNT(*)
。
由於這個問題一再出現,這裏還有一個答案。我希望在這裏爲想要了解「最佳實踐」的初學者添加一些內容。
SELECT COUNT(*) FROM something
計數記錄這是一件容易的事。
SELECT COUNT(1) FROM something
檢索每個記錄1並比計數非空的1,這實質上是計數記錄,只是更復雜。
話雖如此:好的dbms注意到第二個陳述會導致與第一個陳述相同的計數,並相應地重新解釋它,因爲不做不必要的工作。所以通常這兩種表述都會導致相同的執行計劃並且花費相同的時間。
但是從可讀性的角度來看,您應該使用第一條語句。你想計數記錄,所以計數記錄,而不是表達式。僅當您想計算某些事情的非空發生時才使用COUNT(表達式)。
我在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服務。
輕鬆演示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
不知道SQL Server,但在MySQL是沒有區別的。另一方面COUNT(列)不同 – Greg 2009-08-03 10:19:00
不正確。 COUNT(SomeColumn)將僅返回包含SomeColumn的非空值的行數。 COUNT(*)和COUNT('Foo')將返回表中的總行數。 – 2009-08-03 13:51:14
進一步的細節檢查這個 [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