Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何为一个大表构建一个高效的索引,每个子组都必须从中选择一个顶行?_Sql_Sql Server - Fatal编程技术网

Sql 如何为一个大表构建一个高效的索引,每个子组都必须从中选择一个顶行?

Sql 如何为一个大表构建一个高效的索引,每个子组都必须从中选择一个顶行?,sql,sql-server,Sql,Sql Server,我有一个大约2500万行的大表,其中包含以下列:AccountID、ItemID、Date、Price。主键是AccountID、ItemID、Date。我需要有效地选择一组帐户和一组项目的上一个记录日期

我有一个大约2500万行的大表,其中包含以下列:AccountID、ItemID、Date、Price。主键是AccountID、ItemID、Date。我需要有效地选择一组帐户和一组项目的上一个记录日期<@SomeDate中的价格。并非每个账户和项目都有每个日期的记录

基本上,我的存储过程有3个参数:AccountID表、ItemID表和一些日期

我的查询是这样的:

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
               );