查询针对日期范围的条件的性能

时间:2010-08-06 21:10:53

标签: sql sql-server performance date-range sql-execution-plan

这是一张表:

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%)。

查询以简单的方式表示我想要的行,但性能非常糟糕。无论我添加什么索引,它都会进行聚簇索引扫描。我试过了:

  • StartDate
  • StartDate,EndDate

如何改善此查询的效果?


我也审核了this questionthis one的答案。这些解决方案对我的情况没有帮助 - 我真的不想通过创建一个单独的日期表来将查询转换为相等查询(在修改结束日期时会发生什么,或者为null? ),或通过变形数据以适应空间索引。

尽管如此,我仍然愿意对数据结构进行可能的修改(特别是如果它们不添加行,并且不使用奇怪的数据类型)。

2 个答案:

答案 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%的记录,则扫描次数是最佳选项的多倍。如果你有索引,你总是必须在索引中找到数据,然后在表中包含一个记录地址,然后你必须从磁盘获取包含该记录的页面,冒着索引中相邻记录的传播的风险整个磁盘。

如果你真的需要那么多记录并且性能不好,那么可以检查以下内容:

  • 磁盘速度是一个问题吗?
  • 是网络带宽吗?
  • 您是否受限于RAM /缓存?