【问题标题】:Count(*) vs Count(Id) in sql server 2005sql server 2005 中的 Count(*) 与 Count(Id)
【发布时间】:2010-02-08 05:54:36
【问题描述】:

我使用 SQL COUNT 函数从表中获取总数或行数。以下两种说法有区别吗?

SELECT COUNT(*) FROM Table

SELECT COUNT(TableId) FROM Table

另外,在性能和执行时间方面有什么不同吗?

【问题讨论】:

标签: sql-server-2005 count


【解决方案1】:

Thilo 准确地确定了差异...如果column_name 可以是NULLCOUNT( column_name ) 可以返回比COUNT( * ) 小的数字。

但是,如果我可以从稍微不同的角度回答您的问题,因为您似乎专注于性能。

首先,请注意,发出SELECT COUNT(*) FROM table; 可能会阻止写入器,并且它也会被其他读取器/写入器阻止,除非您更改了隔离级别(下意识的往往是WITH (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 查询等待(并最终在您有时间之前使其不准确)阅读)。但否则这将导致比您提出的查询更快的答案,并且不亚于使用WITH (NOLOCK)

【讨论】:

  • Will Count(Primary_Key) 会比上面的查询更好吗?它应该始终给出准确的计数,因为不能有空值的主键。
  • COUNT(PK) 和 COUNT(*) 在这种情况下将是相同的。每个都会给出准确的计数,但仍然可以成为阻止者并且仍然可以被阻止。因此,潜在的性能杀手是否值得准确性取决于您(请记住,如果您使用 NOLOCK “解决”问题,那么您无论如何都会失去准确性)。
  • 我一直认为 Count(PK) 的性能优于 Count(*)。感谢您清除此问题。
  • 优化器知道当它遇到没有 WHERE 子句的 COUNT(*) 时,它应该去寻找最窄的未过滤索引,希望是 PK。
  • 你的评论说你会“好很多” - 你认为这成立吗?它当然适用于 Sybase,但我在 SQL Server 2000 和 2005 上的非常大的表上看到了 select count() 的瞬时返回。也就是说,除非来自 X 的 select count() 绑定在我的事务中我不确定这里对于所需的瞬时共享表锁是否存在性能下降的可信威胁。
【解决方案2】:

count(id) 需要对列进行空检查(可能会针对主键或其他非空列进行优化),因此应该首选 count(*) 或 count(1) (除非你真的想要知道 id 为非空值的行数)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多