优化 select 区别于大型 table

Optimise select distinct from large table

我有一个 table 包含 320,071,712 条记录,我目前正在处理的报告可以按日期过滤记录,之后记录数下降到 145,878,852。不同记录的数量为 107,311,357。

select count(*) 
from [BroadcastOpens] with (nolock) 
where [OpenTimeUtc] >= @StartDate 
and  [OpenTimeUtc] <@EndDate

最耗时的过程是SELECT DISTINCT,到运行用了大约40分钟。

SELECT DISTINCT [SubscriberId],[OpenTimeUtc]  
FROM [BroadcastOpens] WITH (nolock) 
WHERE [OpenTimeUtc] >= @StartDate 
AND [OpenTimeUtc] <@EndDate

我已经在此 table 上为 BroadcastId 和 OpenTimeUtc 列创建了两个索引,它们有助于加快进程,但似乎不太重要。

CREATE NONCLUSTERED INDEX [IX_BroadcastOpens_BroadcastId_Temp] 
ON [dbo].[BroadcastOpens]([BroadcastId])

CREATE NONCLUSTERED INDEX [IX_BroadcastOpens_OpenTimeUtc_Temp] 
ON [dbo].[BroadcastOpens]([OpenTimeUtc])

按照 Martin Smith 的建议,我还在按 [SubscriberId]、[OpenTimeUtc]、[BroadcastId] 分组的 Table BroadcastOpens 上创建了一个索引视图。

CREATE VIEW dbo.vwBroadcastOpensRecords
WITH SCHEMABINDING
AS

SELECT [SubscriberId],[OpenTimeUtc],[BroadcastId], COUNT_BIG(*) as tmp    
from [dbo].[BroadcastOpens] group by [SubscriberId],[OpenTimeUtc],   [BroadcastId]  


CREATE UNIQUE CLUSTERED INDEX CIX_vwBroadcastOpensRecords_Temp ON    
vwBroadcastOpensRecords(SubscriberId, OpenTimeUtc,BroadcastId);

这是导致问题的查询步骤

我现在正在测试这两种方法,看看哪一种能产生更好的性能。

1) 对现有的 tsql 查询没有更改,没有创建非聚集索引。 运行 在生产服务器上 ()

2) 不更改现有的 tsql 查询,在 table 上创建了两个非聚集索引。 运行 在登台服务器上

3) 创建一个索引视图,并修改现有的 tsql 查询以使用这个新的索引视图来替换 table

4) 将以上两个table索引合并为一个,重新运行脚本

CREATE NONCLUSTERED INDEX [IX_BroadcastOpens_BroadcastId_Temp] ON [smpro5].[dbo].[BroadcastOpens]([BroadcastId])
GO

CREATE NONCLUSTERED INDEX [IX_BroadcastOpens_OpenTimeUtc_Temp] ON [smpro5].[dbo].[BroadcastOpens]([OpenTimeUtc])
GO

DROP INDEX IX_BroadcastOpens_BroadcastId_Temp ON [smpro5].[dbo].[BroadcastOpens]
GO

DROP INDEX IX_BroadcastOpens_OpenTimeUtc_Temp ON [smpro5].[dbo].[BroadcastOpens]
GO

CREATE NONCLUSTERED INDEX [IX_BroadcastOpens_OpenTimeUtc_BroadcastId_Temp] ON [dbo].[BroadcastOpens]([OpenTimeUtc], [BroadcastId]);
GO

只是想知道。 Table BroadcastOpens table 不断更新,这是否会影响我创建的索引视图?

采纳任何关于如何改进此查询的建议!

感谢 HABO 和 Martin Smith 的宝贵帮助!

注意:当涉及到索引视图时,不要忘记使用 WITH (NOEXPAND)!

有两个单独的索引对这个查询不是很有帮助。拥有覆盖索引应该可以解决您的问题:

CREATE NONCLUSTERED INDEX [IX_BroadcastOpens_OpenTimeUtc_BroadcastId_Temp] 
ON [dbo].[BroadcastOpens]([OpenTimeUtc], [BroadcastId]);

1) 删除了所有 DISTINCT 关键字 2) 在 BroadcastOpens Table 上创建非聚集索引以加快搜索速度 3) 可能会或可能不会创建索引视图

结果:花费的时间从 42:32 分钟减少到 38:15 分钟。