sql-server sql分组计数 - 计数(*)与计数(1)-SQL Server





count条件 sql行数 (9)


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

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

同样,熟悉SQL标准的人类编码人员可以轻松挑选出COUNT(*) ,这是处理多个供应商的SQL产品时的一项有用技能。

另外,在特殊情况下SELECT COUNT(*) FROM MyPersistedTable; ,这个想法是DBMS可能会为表的基数保存统计数据。

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

只是想知道你们中的任何一个人是否使用Count(1)不是Count(*)并且如果在性能上存在显着差异,或者这只是从过去的日子中提出的遗留习惯?

(特定数据库是SQL Server 2005




没有区别。

原因:

网上书籍说“ COUNT ( { [ [ ALL | DISTINCT ] expression ] | * } )

“1”是一个非空的表达式:因此它与COUNT(*)相同。 优化器认识到它是什么:微不足道。

EXISTS (SELECT * ...相同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年8月

关于DBA.SE的类似问题

编辑,2011年12月

ANSI-92中特别提及COUNT(*) (查找“ Scalar expressions 125 ”)

案件:

a)如果指定了COUNT(*),那么结果是T的基数。

也就是说,ANSI标准认为它显然是你的意思。 由于这种迷信, COUNT(1)已经由RDBMS供应商进行了优化。 否则,将根据ANSI评估

b)否则,让TX为单列表格,这是将<值表达式>应用于T的每一行并消除空值的结果。 如果消除了一个或多个空值,则会发出完成条件:warning-




轻松演示COUNT(*)与COUNT(<some col>) -

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



显然,COUNT(*)和COUNT(1)将始终返回相同的结果。 因此,如果其中一个比另一个慢,这实际上是由于优化器错误。 由于这两种形式在查询中都非常频繁地使用,因此数据库管理系统允许这样的错误保持不固定是没有意义的。 因此,您会发现两种表单的性能在所有主要的SQL DBMS中可能都是相同的。




我在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服务。




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

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

Oracle中的SYS_GUID()是相当计算量的函数。

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

这个查询:

SELECT  COUNT(SYS_GUID())
FROM    t_even

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

但是,这个查询:

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

运行时间为2秒,因为它甚至不尝试评估SYS_GUID() (尽管*是作为COUNT(*)参数)




由于这个问题一再出现,这里还有一个答案。 我希望在这里为想要了解“最佳实践”的初学者添加一些内容。

SELECT COUNT(*) FROM something记录这是一件容易的事。

SELECT COUNT(1) FROM something检索每个记录1,并计数不为null的1,这实质上是对记录进行计数,只是更复杂。

话虽如此:好的dbms注意到第二个陈述会导致与第一个陈述相同的计数,并相应地重新解释它,因为不做不必要的工作。 所以通常这两种表述都会导致相同的执行计划并且花费相同的时间。

但从可读性的角度来看,您应该使用第一条语句。 你想计数记录,所以计数记录,而不是表达式。 仅当您想计算某些事情的非空发生时才使用COUNT(表达式)。




SET STATISTICS TIME ON

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

SQL Server执行时间:
CPU时间= 31 ms,经过时间= 36 ms。

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

SQL Server执行时间:
CPU时间= 46毫秒,经过时间= 37毫秒。

我已经运行了数百次,每次都清除缓存。由于服务器负载不同,结果会不时变化,但几乎总是计数(*)的CPU时间更长。




这可以通过以下代码完成。

CREATE TABLE TestTable
    (FirstCol INT NOT NULL)
    GO
    ------------------------------
    -- Option 1
    ------------------------------
    -- Adding New Column
    ALTER TABLE TestTable
    ADD SecondCol INT
    GO
    -- Updating it with Default
    UPDATE TestTable
    SET SecondCol = 0
    GO
    -- Alter
    ALTER TABLE TestTable
    ALTER COLUMN SecondCol INT NOT NULL
    GO




sql sql-server performance