我在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记录,如果我扩展一点数据时间增加了很多,那么,什么是最好的索引查询?我缺少什么?
答案 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)
此查询的最佳索引是这些列的复合索引,顺序如下:
这允许从索引中完全回答查询。 SqlServer可以扫描范围(WebsiteId
,VisitDate
),然后排除空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。您的表在多个方面严重非规范化。我只希望你知道你在做什么。