这是一张表:
CREATE TABLE Meetings
(
ID int PRIMRY KEY IDENTITY(1,1)
StartDate DateTime NOT NULL,
EndDate DateTime NULL,
Field1 varchar(50),
Field2 varchar(50),
Field3 varchar(50),
Field4 varchar(50)
)
有几千行。数据范围可以是不同的大小(从几天到50年)。
这是一个查询:
DECLARE @ApplicableDate DateTime
SELECT ID, StartDate, EndDate, Field1, Field2, Field3, Field4
FROM Meetings
WHERE StartDate <= @ApplicableDate AND
(EndDate is null || @ApplicableDate <= EndDate)
由于日期范围可能很大,因此可能会返回大部分表格(占行数的20%-50%)。
查询以简单的方式表示我想要的行,但性能非常糟糕。无论我添加什么索引,它都会进行聚簇索引扫描。我试过了:
如何改善此查询的效果?
我也审核了this question和this one的答案。这些解决方案对我的情况没有帮助 - 我真的不想通过创建一个单独的日期表来将查询转换为相等查询(在修改结束日期时会发生什么,或者为null? ),或通过变形数据以适应空间索引。
尽管如此,我仍然愿意对数据结构进行可能的修改(特别是如果它们不添加行,并且不使用奇怪的数据类型)。
答案 0 :(得分:3)
我假设您使用SQL Server进行语法处理。
使ID上的主键成为非聚集索引。
ID int PRIMARY KEY NONCLUSTERED IDENTITY(1,1),
在StartDate列上创建一个聚簇索引。
CREATE CLUSTERED INDEX ix_Meetings_StartDate
ON Meetings (StartDate)
按原样尝试您的查询。尽管数据的存储方式可能与您使用聚簇PK的数据类似,但现在查询引擎会提前知道数据是按开始日期聚类的。
答案 1 :(得分:2)
如果查询返回20%-50%的记录,则扫描次数是最佳选项的多倍。如果你有索引,你总是必须在索引中找到数据,然后在表中包含一个记录地址,然后你必须从磁盘获取包含该记录的页面,冒着索引中相邻记录的传播的风险整个磁盘。
如果你真的需要那么多记录并且性能不好,那么可以检查以下内容: