Sql server 2005 sql server 2005中的计数(*)与计数(Id)

Sql server 2005 sql server 2005中的计数(*)与计数(Id),sql-server-2005,count,Sql Server 2005,Count,我使用SQLCOUNT函数从表中获取总行数。以下两种说法有什么不同吗 SELECT COUNT(*) FROM Table 及 此外,在性能和执行时间方面是否有任何差异?count(id)需要空检查列(可能会针对主键或非空列进行优化),因此应首选count(*)或count(1)(除非您确实想知道id值为非空的行数).Thilo准确地指出了差异COUNT(column\u name)可以返回比COUNT(*)更低的数字 然而,如果我能从一个稍微不同的角度来回答你的问题,因为你似乎专注于表现 首

我使用SQL
COUNT
函数从表中获取总行数。以下两种说法有什么不同吗

SELECT COUNT(*) FROM Table


此外,在性能和执行时间方面是否有任何差异?

count(id)需要空检查列(可能会针对主键或非空列进行优化),因此应首选count(*)或count(1)(除非您确实想知道id值为非空的行数).

Thilo准确地指出了差异<如果
column\u name
可以为
NULL
,则code>COUNT(column\u name)可以返回比
COUNT(*)更低的数字

然而,如果我能从一个稍微不同的角度来回答你的问题,因为你似乎专注于表现

首先,请注意,从表中选择COUNT(*)
可能会阻止编写者,并且它也会被其他读者/编写者阻止,除非您改变隔离级别(膝跳倾向于
使用(NOLOCK)
,但我看到有很多人最终开始相信RCSI)。这意味着,当您读取数据以获得“准确”计数时,所有这些DML请求都在堆积,当您最终释放所有锁时,闸门打开,一系列插入/更新/删除活动发生,您的“准确”计数也随之增加

如果您需要绝对事务一致且准确的行计数(即使它仅在返回数字所需的毫秒数内有效),则
SELECT count(*)
是您唯一的选择

另一方面,如果您试图获得99.9%的准确度,那么您最好使用以下查询:

SELECT row_count = SUM(row_count)
  FROM sys.dm_db_partition_stats
  WHERE [object_id] = OBJECT_ID('dbo.Table')
  AND index_id IN (0,1);
(SUM用于解释已分区的表-如果您不使用表分区,可以不使用它。)


此DMV为表维护准确的行计数,但当前参与事务的行除外-这些事务将使您的
SELECT COUNT
查询等待(并最终在您有时间读取之前使其不准确)。但是,否则,这将导致比您建议的查询更快的答案,并且与使用
和(NOLOCK)
相比,准确度不低于将计数(主键)将是比上述查询更好的选择?它应该总是给出一个准确的计数,因为主键不能有空值。在这种情况下,计数(PK)和计数(*)是相同的。每一个都会给出一个准确的计数,但仍然可以是阻止者,并且仍然可以被阻止。因此,潜在的性能杀手是否值得精确取决于您(请记住,如果您使用NOLOCK“解决”问题,您无论如何都会失去您的精确性)。我一直认为Count(PK)的性能优于Count(*)。感谢您澄清这一点。优化器知道当它遇到COUNT(*)且不带WHERE子句时,它应该在最窄的非过滤索引之后,这很可能就是PK。您的评论说您将“过得更好”-您认为这是否成立?它当然适用于Sybase,但我已经看到在SQL Server 2000和2005上非常大的表上立即返回select count()。i、 e.除非X中的select count()绑定在事务中,否则我不确定所需的临时共享表锁是否存在性能下降的可信威胁。已经回答了,但这里对此进行了很好的讨论:
SELECT row_count = SUM(row_count)
  FROM sys.dm_db_partition_stats
  WHERE [object_id] = OBJECT_ID('dbo.Table')
  AND index_id IN (0,1);