我的MS SQL数据库中有一个大型(> 1亿行)表,其中包含以下列:
Id int not null,
ObjectId int not null,
Timestamp datetime not null
State int not null
Id
是表的主键(并且在其上有聚集索引)。我在Timestamp和ObjectId上添加了一个非聚集索引(按此顺序)。在ObjectId
中大约有2000个不同的值。现在我想执行以下查询:
SELECT ObjectId, MAX(Timestamp) FROM Table GROUP BY ObjectId
大约需要4秒钟,这对我的应用程序来说太慢了。执行计划表明97%的运行时用于非聚集索引的索引扫描。
在表的副本上,我在ObjectId和Timestamp上创建了聚集索引。结果运行时是相同的,执行计划说现在正在对聚集索引进行索引扫描。
是否有其他的可能性,以提高运行时不拆分表的数据到多个表?
我可以向您提出另一个答案,添加一个布尔列LAST并将objecd的LAST true更新为false,然后为这个objecd插入现在行,其中LAST为true。在ObjectID和LAST上创建索引。查询很简单:
SELECT ObjectId, Timestamp FROM Table where LAST = true
没有更多的group by和fullscan,但每个insert都有一个更新。
4秒对于在数据库中有更多100M行的工作来说还不错。您可以每天将一些数据归档到另一个表中以保存历史数据。您可以将所有数据归档到另一个表中,并删除旧的更改对象:
delete from TABLE where Id in (select t1.Id from Table t1, Table t2
where t1.ObjectId = t2.ObjectId and t1.Timestamp < t2.Timestamp )
对于这个特定的查询,(ObjectId, Timestamp)上的索引将是最优的。(ObjectId, Timestamp DESC)有可能执行得更快。