只是想知道你们中是否有人使用Count(1)而不是Count(*),是否在性能上有明显的差异,或者这只是过去几天养成的传统习惯?
特定的数据库是SQL Server 2005。
只是想知道你们中是否有人使用Count(1)而不是Count(*),是否在性能上有明显的差异,或者这只是过去几天养成的传统习惯?
特定的数据库是SQL Server 2005。
当前回答
有一篇文章显示,Oracle上的COUNT(1)只是COUNT的别名(*),并提供了相关证据。
我将引用一些部分:
数据库软件的一部分叫做“Optimizer”,在官方文档中定义为“内置数据库软件,可确定执行SQL语句”。优化器的一个组件叫做“变压器”,其作用是确定重写将原始SQL语句转换为语义等价的SQL语句这可能更有效。您想看看优化器在编写查询时做什么吗使用COUNT(1)?
对于具有ALTER SESSION权限的用户,您可以放置tracefile_identifier,启用优化器跟踪并运行COUNT(1)select,例如:select/*test-1*/COUNT(1,FROM employees;。
之后,您需要本地化跟踪文件,这可以通过SELECT VALUE FROM V$DIAG_INFO WHERE NAME='DIAG trace';来完成;。稍后在文件中,您将发现:
SELECT COUNT(*) “COUNT(1)” FROM “COURSE”.”EMPLOYEES” “EMPLOYEES”
如您所见,它只是COUNT(*)的别名。
另一个重要的评论是:20年前,在Oracle 7.3之前,COUNT(*)确实更快:
自7.3以来,计数(1)已重写为计数(*),因为Oracle类似自动调整mythic语句。在早期的Oracle7中,oracle必须在确定之前对每一行求值(1),作为函数存在非确定性。20年前,count(*)更快
对于另一个数据库(如SqlServer),应分别对每个数据库进行研究。
我知道这个问题是针对SQL Server的,但SO中关于同一主题的其他问题(没有提到特定的数据库)已关闭,并标记为与此答案重复。
其他回答
我希望优化器能够确保在奇怪的边缘情况之外没有真正的差异。
与任何事情一样,唯一真正的方法就是衡量你的具体情况。
也就是说,我一直使用COUNT(*)。
在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(*)的参数)
有一篇文章显示,Oracle上的COUNT(1)只是COUNT的别名(*),并提供了相关证据。
我将引用一些部分:
数据库软件的一部分叫做“Optimizer”,在官方文档中定义为“内置数据库软件,可确定执行SQL语句”。优化器的一个组件叫做“变压器”,其作用是确定重写将原始SQL语句转换为语义等价的SQL语句这可能更有效。您想看看优化器在编写查询时做什么吗使用COUNT(1)?
对于具有ALTER SESSION权限的用户,您可以放置tracefile_identifier,启用优化器跟踪并运行COUNT(1)select,例如:select/*test-1*/COUNT(1,FROM employees;。
之后,您需要本地化跟踪文件,这可以通过SELECT VALUE FROM V$DIAG_INFO WHERE NAME='DIAG trace';来完成;。稍后在文件中,您将发现:
SELECT COUNT(*) “COUNT(1)” FROM “COURSE”.”EMPLOYEES” “EMPLOYEES”
如您所见,它只是COUNT(*)的别名。
另一个重要的评论是:20年前,在Oracle 7.3之前,COUNT(*)确实更快:
自7.3以来,计数(1)已重写为计数(*),因为Oracle类似自动调整mythic语句。在早期的Oracle7中,oracle必须在确定之前对每一行求值(1),作为函数存在非确定性。20年前,count(*)更快
对于另一个数据库(如SqlServer),应分别对每个数据库进行研究。
我知道这个问题是针对SQL Server的,但SO中关于同一主题的其他问题(没有提到特定的数据库)已关闭,并标记为与此答案重复。
COUNT(1)与COUNT。关于计数空列的问题,这可以直接演示COUNT(*)和COUNT之间的差异(<somecol>)--
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
我在一个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服务。