7

我有一个包含超过 10 亿行时间序列数据的表,具有出色的插入性能,但(有时)选择性能很差。

tblTrendDetails(PK排序如图):

PK  TrendTime    datetime
PK  CavityId     int
PK  TrendValueId int
    TrendValue   real

该表不断地拉入新数据并清除旧数据,因此插入和删除性能需要保持敏捷。

执行如下查询时,性能很差(30 秒):

SELECT * 
FROM tblTrendDetails
WHERE TrendTime BETWEEN @inMinTime AND @inMaxTime
  AND CavityId = @inCavityId
  AND TrendValueId = @inTrendId

如果我再次执行相同的查询(时间相似,但任何@inCavityIdor @inTrendId),性能非常好(1 秒)。性能计数器显示磁盘访问是第一次运行查询的罪魁祸首。

关于如何在不(显着)对插入或删除性能产生不利影响的情况下提高性能的任何建议?欢迎任何建议(包括完全更改底层数据库)。

4

1 回答 1

9

相同或相似数据的后续查询运行得更快的事实可能是由于 SQL Server缓存了您的数据。也就是说,是否可以加快这个初始查询的速度?

验证查询计划:

我的猜测是您的查询应该导致索引搜索而不是索引扫描(或更糟糕的是,表扫描)。请使用SET SHOWPLAN_TEXT ON;或类似功能对此进行验证。使用betweenand=作为您的查询确实应该利用聚集索引,尽管这值得商榷

索引碎片:

在所有这些插入和删除之后,您的聚集索引(在本例中为主键)可能非常碎片化。我可能会用DBCC SHOWCONTIG (tblTrendDetails).

您可以使用 对表的索引进行碎片整理DBCC INDEXDEFRAG (MyDatabase, tblTrendDetails)。这可能需要一些时间,但可以让表保持可访问性,并且您可以停止操作而不会产生任何令人讨厌的副作用。

您可能需要更进一步并使用DBCC DBREINDEX (tblTrendDetails). 不过,这是一个离线操作,因此您应该只在不需要访问表时才执行此操作。

此处描述了一些差异:Microsoft SQL Server 2000 索引碎片整理最佳实践

请注意,您的事务日志可能会因对大表进行碎片整理而增长很多,并且可能需要很长时间。

分区视图:

如果这些不能解决问题(或者碎片不是问题),您甚至可能希望查看分区视图,在其中您为各种记录范围创建一堆基础基表,然后将它们全部合并到一个视图中(替换原来的表)。

更好的东西:

如果这些选择的性能是真正的业务需求,您也许可以为更好的硬件提供理由:更快的驱动器、更多的内存等。如果您的驱动器速度是原来的两倍,那么这个查询将在一半的时间内运行,是的? 此外,这可能对您不适用,但我只是发现较新版本的 SQL Server 确实更快,具有更多选项并且更好地维护。我很高兴将公司的大部分数据移至 2008R2。但我离题了...

于 2012-10-23T21:04:08.233 回答