【问题标题】:Improve performance of slow sub query in SQL Server提高 SQL Server 中慢速子查询的性能
【发布时间】:2019-11-19 18:35:11
【问题描述】:

我有一个包含 130 万行的表。

查询 #1 在 SQL Server 2016 Management Studio 中运行需要 29 秒。

查询 #1:

select 
    *,
    (select Count(*)
     from [dbo].[Results] t2
     where t2.RaceDate < t1.RaceDate
       and t1.HorseName = t2.HorseName
       and t2.Position = '1'
       and t1.CourseName = t2.CourseName
       and t2.CountryCode = 'GB') as [CourseDistanceWinners]
from 
    [dbo].[Results] t1

但是查询 #2 需要几个小时,唯一的区别是 t1.HorseName = t2.HorseNamet1.TrainerName = t2.TrainerName。将会有更多的比赛,但在 TrainerName 上的比赛比在 HorseName 上的比赛要多,但我没想到会有几个小时。

查询 #2:

select 
    *,
    (select Count(*)
     from [dbo].[Results] t2
     where t2.RaceDate < t1.RaceDate
       and t1.TrainerName = t2.TrainerName
       and t2.Position = '1'
       and t1.CourseName = t2.CourseName
       and t2.CountryCode = 'GB') as [CourseDistanceWinners]
from 
    [dbo].[Results] t1

我已经设法使用以下技术将查询缩短到 15 分钟,但我仍然认为这是一个很长的时间。我还能做些什么来提高 Query2 的性能或重写它以提高性能吗?

到目前为止我已经尝试过什么

  1. 我已将[TrainerName] [nvarchar](255) NULL, 更改为[TrainerName] [nvarchar](50) NULL,

  2. 我添加了一个复合索引和几个非聚集索引

    CREATE INDEX idx_HorseName
    ON [dbo].[Results] (HorseName);
    
    CREATE INDEX idx_TrainerName
    ON [dbo].[Results] (TrainerName);
    
    CREATE INDEX idx_CourseName
    ON [dbo].[Results] (CourseName);
    
    CREATE INDEX idx_Position
    ON [dbo].[Results] (Position);
    
    CREATE INDEX idx_JockeyName
    ON [dbo].[Results] (JockeyName);
    
    CREATE INDEX idx_RaceDate
    ON [dbo].[Results] (RaceDate);
    
    CREATE INDEX idx_TrainerComposite
    ON [dbo].[Results] (TrainerName, RaceDate, CourseName);
    

更多信息:

表结构:

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Results]
(
    [CountryCode] [NVARCHAR](50) NULL,
    [CourseName] [NVARCHAR](50) NULL,
    [HorseName] [NVARCHAR](50) NOT NULL,
    [HorseSuffix] [NVARCHAR](5) NOT NULL,
    [JockeyName] [NVARCHAR](255) NULL,
    [OwnerName] [NVARCHAR](255) NULL,
    [Position] [NVARCHAR](255) NULL,
    [PublishedTime] [NVARCHAR](6) NOT NULL,
    [RaceDate] [DATETIME] NOT NULL,
    [RaceTitle] [NVARCHAR](255) NULL,
    [StallPosition] [NVARCHAR](255) NULL,
    [TrainerName] [NVARCHAR](50) NULL,
    [Rating] [INT] NULL,

    CONSTRAINT [PK_Results_1] 
        PRIMARY KEY CLUSTERED ([HorseName] ASC,
                               [HorseSuffix] ASC,
                               [PublishedTime] ASC,
                               [RaceDate] ASC)
                    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                          IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                          ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

查询 #1 执行计划:

查询#2执行计划:

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    使用窗口函数!

    select r.*,
           sum(case when position = 1 and country_code = 'GB' then 1 else 0 end) over
               (partition by horsename, coursename
                order by racedate
                rows between unbounded preceding and 1 preceding
               ) as CourseDistanceWinners
    from [dbo].[Results] r
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-03
      • 2015-02-18
      • 2019-03-20
      • 2015-08-01
      • 1970-01-01
      相关资源
      最近更新 更多