我有一张超过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
如果我再次执行相同的查询(具有相似的时间,但任何@inCavityId
或@inTrendId
),则表现非常好(1秒)。性能计数器显示磁盘访问是第一次运行查询时的罪魁祸首。
有关如何在不显着影响插入或删除性能的情况下提高性能的任何建议?欢迎任何建议(包括完全更改底层数据库)。
答案 0 :(得分:7)
相同或类似数据的后续查询运行得更快的事实可能是由于SQL Server caching your data。也就是说,是否可以加快初始查询速度?
验证查询计划:
我的猜测是你的查询应该导致索引搜索而不是索引扫描(或者更糟糕的是,表扫描)。请使用SET SHOWPLAN_TEXT ON;
或类似功能进行验证。使用between
和=
作为您的查询确实take advantage of the clustered index,that's debatable。
索引碎片:
在所有这些插入和删除之后,您的聚簇索引(在这种情况下为主键)可能会非常碎片化。我可能会用DBCC SHOWCONTIG (tblTrendDetails)
检查这个。
您可以使用DBCC INDEXDEFRAG (MyDatabase, tblTrendDetails)
对表的索引进行碎片整理。
这可能需要一些时间,但可以让表格保持可访问状态,您可以停止操作而不会产生任何令人讨厌的副作用。
您可能需要更进一步并使用DBCC DBREINDEX (tblTrendDetails)
。但这是一个脱机操作,所以只有在不需要访问表时才应该这样做。
此处描述了一些差异:Microsoft SQL Server 2000 Index Defragmentation Best Practices。
请注意,您的事务日志可能会因对大型表进行碎片整理而增长很多,而且可能需要很长时间。
分区视图:
如果这些不能解决问题(或碎片不是问题),你甚至可以查看partitioned views,在其中为各种记录范围创建一堆基础表,然后联合它们都在视图中(替换原始表格)。
更好的东西:
如果这些选择的性能是真正的业务需求,您可以为更好的硬件提供支持:更快的驱动器,更多的内存等。如果您的驱动器速度是原来的两倍,那么此查询将以一半的速度运行时间,是吗?此外,这对您来说可能不适用,但我只是发现更新版本的SQL Server可以更快地获得更多选项并更好地维护。我很高兴将我公司的大部分数据转移到2008R2。但我离题了......