Sql 如何为一个大表构建一个高效的索引,每个子组都必须从中选择一个顶行?
我有一个大约2500万行的大表,其中包含以下列:AccountID、ItemID、Date、Price。主键是AccountID、ItemID、Date。我需要有效地选择一组帐户和一组项目的上一个记录日期<@SomeDate中的价格。并非每个账户和项目都有每个日期的记录 基本上,我的存储过程有3个参数:AccountID表、ItemID表和一些日期 我的查询是这样的:Sql 如何为一个大表构建一个高效的索引,每个子组都必须从中选择一个顶行?,sql,sql-server,Sql,Sql Server,我有一个大约2500万行的大表,其中包含以下列:AccountID、ItemID、Date、Price。主键是AccountID、ItemID、Date。我需要有效地选择一组帐户和一组项目的上一个记录日期
SELECT *
FROM (
SELECT p.*,
ROW_NUMBER() OVER
(PARTITION BY p.AccountID,p.ItemID ORDER BY p.Date DESC) RN
FROM Prices p INNER JOIN @Accounts acc ON acc.ID=p.AccountID
INNER JOIN @Items items ON items.ID=p.ItemID
WHERE Date<=@SomeDate)T
WHERE RN=1
这工作正常,但有点慢。
考虑到我没有任何存储限制,并且写时间不是一个因素,什么样的索引可以使这个查询运行得更快?
还有其他方法可以优化此查询吗
谢谢
编辑:
我还应该提到,我有一个基于主键的聚集索引,主键被聚集索引Seek op查询命中。我使用的UDT也被索引
是否有任何方法可以在数量级上改进此查询?我将把查询改写为:
SELECT *
FROM (SELECT p.*,
ROW_NUMBER() OVER (PARTITION BY p.AccountID, p.ItemID ORDER BY p.Date DESC) as RN
FROM Prices p
WHERE p.Date <= @SomeDate)
) p INNER JOIN
@Accounts acc
ON acc.ID = p.AccountID INNER JOIN
@Items items
ON items.ID = p.ItemID
WHERE RN = 1;
此版本可以使用价格的主键索引。您还需要@accountsid和@itemsid上的索引。您是否尝试查看执行计划?如果有一个索引可以帮助你,它通常会给你一个脚本来创建它。通常,索引应该基于WHERE或on子句中您将经常使用的任何列进行搜索,并包括您可能想要返回的任何列。我确实有一个基于主键的索引,并且UDT参数也被索引。我希望在数量级上有进一步的改进,最好是。实际上,您编写的第一个查询运行速度比我的快2倍。虽然这绝对是件好事,但我的目标是实现一个数量级的改进。顺便说一句,你的和我的都用聚集索引Seek op命中主键索引。你的第二个建议在逻辑上是不正确的。你的价格主键的p.date部分是否标记为下降?如果存在排序,这有助于消除执行计划中的排序。是的,它是AccountID ASC、ItemID ASC、Date DESC.@UriK。第二个版本应该是相同的,假设该日期没有重复的价格。@GordonLinoff你是对的。我没有注意到外部子查询上的内部联接。不管怎样,它的速度是我的两倍。我这么说是因为我希望找到一个数量级的改进。
SELECT *
FROM Prices p INNER JOIN
@Accounts acc
ON acc.ID = p.AccountID INNER JOIN
@Items items
ON items.ID = p.ItemID
WHERE p.Date = (SELECT MAX(p2.Date)
FROM prices p2
WHERE p2.Date <= @SomeDate AND
p2.AccountId = p.AccountId AND p2.ItemId = p.ItemId
);