【问题标题】:Improve performance on SQL query with select top 1-statement before from-statement在 from-statement 之前使用 select top 1-statement 提高 SQL 查询的性能
【发布时间】:2016-01-08 08:11:05
【问题描述】:

我有一个很长的复杂 SQL 查询(在 Microsoft SQL Server 2012 中),我需要在其中提高性能。我有一个问题,SQL 查询在 from 语句之前有一个“select top 1”。很难解释,所以在这篇文章下面我写了一个关于这个问题的示例 SQL 查询:

select 
    Player.Firstname, 
    Player.Lastname,
    LastGameGoals = 
      (select top 1 Goals
       from PlayerSummary 
       where PlayerSummary.PlayerID = Player.PlayerId 
       order by PlayerSummaryId desc)
from Player

上面的 SQL 获取曲棍球运动员的名字和姓氏,以及特定球员在最后一场比赛中的进球数。由于数据库非常大,由于 select top 1-statement,它会变得非常慢。

我当然可以添加一个索引以获得更好的性能,但我可以避免在每个玩家行上执行“选择前 1”吗?

如何提高性能?

【问题讨论】:

  • 那么,为什么没有索引呢?查询计划是否真的建议为每一行单独的select top 1?这看起来很奇怪。
  • 对于某些TOP n 查询,SQL 服务器存在缺陷。看到这个:dba.stackexchange.com/questions/143218/…

标签: sql performance sql-server-2012


【解决方案1】:

对于这个声明:

LastGameGoals = 
  (select top 1 Goals
   from PlayerSummary 
   where PlayerSummary.PlayerID = Player.PlayerId 
   order by PlayerSummaryId desc)

你想要一个索引。最好的索引是PlayerSummery(PlayerId, PlayerSummaryId, Goals)。这是子查询的覆盖索引,所以它应该对性能有很大的影响。

我不明白您为什么要避免使用索引。您可以使用窗口函数重写查询:

select p.*,
       ps.goals as LastGameGoals
from player p left join
    (select ps.*,
            row_number() over (partition by playerId order by PlayerSummaryId desc) as seqnum
     from PlayerSummary ps
    ) ps
    on p.playerid = ps.playerid and ps.seqnum = 1;

你应该测试一下,但我猜索引会更快。

【讨论】:

  • 为什么不在PlayerSummary(PlayerId, PlayerSummaryID) INCLUDE(Goals) 上建立索引?您无需在Goals 上查找,只需找到它即可。
  • 我试图避免索引的原因是我了解到在“from”语句之前的“select”语句等于性能不佳。我认为可以进行某种连接而不是选择来提高性能,而不是添加索引。但是,如果无法以另一种方式做到这一点,我对答案感到满意。 :) 谢谢!
  • @Delta 。 . .让我们说这是一个有很多例外的一般规则。相关子查询不会产生平均不良性能。有时,它们实际上是解决问题的最佳方法。如果它让您感觉更好,您可以改用outer apply。语法几乎相同,但相关子查询移至from 子句。
  • @JonHanna 。 . .这是为查询创建覆盖索引的另一种可行方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-12
  • 2011-01-03
  • 2018-11-09
  • 1970-01-01
  • 1970-01-01
  • 2014-03-23
  • 1970-01-01
相关资源
最近更新 更多