只是想知道你们中是否有人使用Count(1)而不是Count(*),是否在性能上有明显的差异,或者这只是过去几天养成的传统习惯?

特定的数据库是SQL Server 2005。


当前回答

在SQL Server中,这些语句产生相同的计划。

与流行的观点相反,在甲骨文公司,他们也是如此。

Oracle中的SYS_GUID()是一个计算密集型函数。

在我的测试数据库中,t_even是一个包含1000000行的表

此查询:

SELECT  COUNT(SYS_GUID())
FROM    t_even

运行48秒,因为函数需要计算返回的每个SYS_GUID(),以确保它不是NULL。

但是,此查询:

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

运行仅2秒,因为它甚至不尝试计算SYS_GUID()(尽管*是COUNT(*)的参数)

其他回答

我在一个8GB的RAM超级存储箱上对SQL Server 2012进行了快速测试。您可以自己查看结果。在运行这些测试时,我没有运行除SQLServerManagementStudio之外的任何其他窗口应用程序。

我的表架构:

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

雇员表中的记录总数: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(1)将始终返回相同的结果。因此,如果一个比另一个慢,这实际上是由于优化器错误。由于这两种形式在查询中都使用得非常频繁,所以DBMS不允许这样的错误保持不变是没有意义的。因此,您将发现两种形式的性能(可能)在所有主要的SQL DBMS中都是相同的。

在SQL-92标准中,COUNT(*)特别表示“表表达式的基数”(可以是基表、`VIEW、派生表、CTE等)。

我认为COUNT(*)很容易解析。使用任何其他表达式都需要解析器确保它不引用任何列(COUNT('a'),其中a是文本,COUNT(a),如果a是列,可以产生不同的结果)。

同样,COUNT(*)可以由熟悉SQL标准的程序员轻松识别,这是一种在使用多个供应商的SQL产品时非常有用的技能。

此外,在特殊情况下,SELECT COUNT(*)FROM MyPersistedTable;,其思想是DBMS可能保存表基数的统计信息。

因此,因为COUNT(1)和COUNT(*)在语义上是等价的,所以我使用COUNT(*)。

我希望优化器能够确保在奇怪的边缘情况之外没有真正的差异。

与任何事情一样,唯一真正的方法就是衡量你的具体情况。

也就是说,我一直使用COUNT(*)。

COUNT(*)和COUNT(1)在结果和性能方面是相同的。