如何使用索引加速当前查询

时间:2015-09-24 23:51:22

标签: sql sql-server tsql indexing azure-sql-database

我在Azure SQL数据库中使用v12服务器,我有下表:

CREATE TABLE [dbo].[AudienceNiches]( [Id] [bigint] IDENTITY(1,1) NOT NULL, [WebsiteId] [nvarchar](128) NOT NULL, [VisitorId] [nvarchar](128) NOT NULL, [VisitDate] [datetime] NOT NULL, [Interest] [nvarchar](50) NULL, [Gender] [float] NULL, [AgeFrom18To24] [float] NULL, [AgeFrom25To34] [float] NULL, [AgeFrom45To54] [float] NULL, [AgeFrom55To64] [float] NULL, [AgeFrom65Plus] [float] NULL, [AgeFrom35To44] [float] NULL, CONSTRAINT [PK_AudienceNiches] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) )

我正在执行此查询:(更新的查询)

`select  a.interest, count(interest) from (
select visitorid, interest
from audienceNiches
WHERE WebsiteId = @websiteid
AND VisitDate >= @startdate
AND VisitDate <= @enddate
group by visitorid, interest) as a
group by a.interest`

我有以下索引(所有ASC):

idx_WebsiteId_VisitDate_VisitorId idx_WebsiteId_VisitDate idx_VisitorId idx_Interest

问题是我的查询返回18K行大约需要5秒,整个表有8.8M记录,如果我扩展一点数据时间增加了很多,那么,什么是最好的索引查询?我缺少什么?

5 个答案:

答案 0 :(得分:2)

我很难在没有测试数据的情况下编写SQL,但看看这是否能给你带来更好执行时间的结果。

SELECT interest, count(distinct visitorid)
FROM audienceNiches
WHERE WebsiteId = @websiteid
AND VisitDate between @startdate and @enddate
AND interest is not null 
GROUP BY interest

答案 1 :(得分:2)

此查询的最佳索引是这些列的复合索引,顺序如下:

  • WebsiteId
  • VisitDate
  • 兴趣
  • VisitorId

这允许从索引中完全回答查询。 SqlServer可以扫描范围(WebsiteIdVisitDate),然后排除空Interest,最后从索引中计算不同的VisitorIds。索引条目的顺序正确,以便有效地执行这些操作。

答案 2 :(得分:1)

索引可能需要几乎无限量的理解,但在您的情况下,我认为通过将WebsiteId和VisitDate索引为单独的索引,您会看到良好的性能提升。

尽管确保您的索引处于良好状态非常重要。您需要通过保持最新统计信息并定期重建索引来维护它们。

最后,您应该在调整查询性能时检查查询计划。 SQL Server会告诉您它是否认为它会从索引的一列(或多列)中受益,并且还会提醒您其他与性能相关的问题。

在Management Studio中按Ctrl + L,查看查询的内容。

答案 3 :(得分:1)

您的查询可以用这种方式编写,因为在最终结果集中,您不会从表audienceNiches中提取列visitorid,因此无需编写两个不同级别的group by。请查看此查询,并告知我是否仍然面临性能问题。

select  interest, count(interest)
from audienceNiches
WHERE WebsiteId = @websiteid
AND VisitDate >= @startdate
AND VisitDate <= @enddate
group by interest

答案 4 :(得分:0)

首先,您的更新查询可以有效地减少到:

select an.Interest, count(an.Interest)
from dbo.AudienceNiches an
where an.WebsiteId = @WebSiteId
    and an.VisitDate between @startdate and @enddate
group by an.Interest;

其次,根据数据的基数,以下索引之一将提供最佳性能:

create index IX_AudienceNiches_WebSiteId_VisitDate_Interest on dbo.AudienceNiches
(WebSiteId, VisitDate, Interest);

create index IX_AudienceNiches_VisitDate_WebSiteId_Interest on dbo.AudienceNiches
(VisitDate, WebSiteId, Interest);

然而,随着您的数据增长,我认为最终后者平均会变得更有效率。

P.S。您的表在多个方面严重非规范化。我只希望你知道你在做什么。