在NULLABLE列上进行SQL Server分组

时间:2016-01-12 10:30:43

标签: sql-server database

我在SQL Server(带有遗留数据库)中有一种情况,我无法理解为什么?

我有一个表A(大约200万行),其列CODE允许null。具有CODE = NULL的行数只是几行(<10行)。当我运行查询时:

select code, sum(C1)
from A
-- where code is not null
group by code;

它永远运行。但是当我取消对where子句的评论时,它需要大约1.5秒(仍然太慢,对吗?)

这里的任何人都可以帮我指出造成这种情况的可能原因吗?

执行计划添加: enter image description here

2 个答案:

答案 0 :(得分:1)

作为一般规则,传统索引不能存储NULL值。因此,即使您在代码上有索引,您的WHERE条件也无法从该索引中受益。

如果索引中包含C1(我假设它是非NULL),那么情况会有所不同,因为所有元组(代码= NULL,C1 =(某些值))都可以并且将会是索引。根据你的问题,这些很少;因此,只需返回所有这些元组的行,SQL Server就可以获得相当大的加速。

答案 1 :(得分:1)

首先,谈谈绩效。我们在您的案例中有几种变体。

索引视图 -

IF OBJECT_ID('dbo.t', 'U') IS NOT NULL
    DROP TABLE dbo.t
GO

CREATE TABLE dbo.t (
    ID INT IDENTITY PRIMARY KEY,
    Code VARCHAR(10) NULL,
    [Status] INT NULL
)
GO

ALTER VIEW dbo.v
WITH SCHEMABINDING
AS
    SELECT Code, [Status] = SUM(ISNULL([Status], 0)), Cnt = COUNT_BIG(*)
    FROM dbo.t
    WHERE Code IS NOT NULL
    GROUP BY Code
GO

CREATE UNIQUE CLUSTERED INDEX ix ON dbo.v (Code)

SELECT Code, [Status]
FROM dbo.v

过滤索引 -

CREATE NONCLUSTERED INDEX ix ON dbo.t (Code)
    INCLUDE ([Status])
    WHERE Code IS NOT NULL

将等待你的第二个执行计划。