【问题标题】:Performance difference between Select count(ID) and Select count(*)Select count(ID) 和 Select count(*) 之间的性能差异
【发布时间】:2016-12-24 15:43:22
【问题描述】:

下面有两个查询返回 ID 列的计数,不包括 NULL 值 第二个查询将返回表中所有行的计数,包括 NULL 行。

select COUNT(ID) from TableName  

select COUNT(*) from TableName

我的困惑: 有什么性能差异吗?

【问题讨论】:

  • 逻辑表明对 NULL 的测试会减慢速度 - 差异可能以毫秒为单位,除非您有数百万条记录。
  • @Kamil:虽然相似,但不是同一个问题。您的链接与表达查询的 3 种不同方式有关,这将产生完全相同的结果。在这种情况下,这 2 个查询不会返回相同的结果。根据 OP 的描述,ID 可以为空,但这很奇怪。我希望OP的描述是正确的。
  • TableName的定义是什么? ID 真的像您建议的那样可以为空吗?如果是奇怪的名字。你有什么索引?
  • 你说:包括 NULL 行 .. 你到底是什么意思?您是否可能只向我们展示部分查询?您实际上是在谈论带有左连接的查询吗?
  • 这是一个具有单个 Null 列的测试表。根据答案,我会选择生产环境选项之一

标签: sql performance tsql select count


【解决方案1】:

TL/DR:计划可能不一样,您应该在适当的情况下进行测试 数据并确保您拥有正确的索引,然后根据您的调查选择最佳解决方案。

查询计划可能不同,具体取决于 COUNT 函数中使用的列的索引和可空性。

在下面的示例中,我创建了一个表并用一百万行填充它。 除“b”列外,所有列均已编入索引。

结论是,其中一些查询确实会产生相同的执行计划,但大多数是不同的。

这是在 SQL Server 2014 上测试的,目前我无法访问 2012 的实例。您应该自己测试以找出最佳解决方案。

create table t1(id bigint identity, 
                dt datetime2(7) not null default(sysdatetime()), 
                a char(800) null, 
                b char(800) null,
                c char(800) null);

-- We will use these 4 indexes. Only column 'b' does not have any supporting index on it.
alter table t1 add constraint [pk_t1]  primary key NONCLUSTERED (id);
create clustered index cix_dt on t1(dt);
create nonclustered index ix_a on t1(a);
create nonclustered index ix_c on t1(c);

insert into T1 (a, b, c) 
select top 1000000 
    a = case when low = 1 then null else left(REPLICATE(newid(), low), 800) end, 
    b = case when low between 1 and 10 then null else left(REPLICATE(newid(), 800-low), 800) end,
    c = case when low between 1 and 192 then null else left(REPLICATE(newid(), 800-low), 800) end
from master..spt_values 
cross join (select 1 from master..spt_values) m(ock)
where type = 'p';


checkpoint;

-- All rows, no matter if any columns are null or not
-- Uses primary key index
select count(*) from t1;

-- All not null, 
-- Uses primary key index
select count(id) from t1;

-- Some values of 'a' are null
-- Uses the index on 'a'
select count(a) from t1;

-- Some values of b are null
-- Uses the clustered index
select count(b) from t1;

-- No values of dt are null and the table have a clustered index on 'dt'
-- Uses primary key index and not the clustered index as one could expect.
select count(dt) from t1;

-- Most values of c are null
-- Uses the index on c
select count(c) from t1;

现在,如果我们更明确地说明我们希望计数做什么,会发生什么?如果我们告诉查询规划器我们只想获取不为空的行,那会改变什么吗?

-- Homework!
-- What happens if we explicitly count only rows where the column is not null? What if we add a filtered index to support this query?
-- Hint: It will once again be different than the other queries.
create index ix_c2 on t1(c) where c is not null;
select count(*) from t1 where c is not null;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-19
    • 1970-01-01
    • 1970-01-01
    • 2012-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多