2009-08-03 135 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