【问题标题】:Properly Index an UNPIVOT SQL query正确索引 UNPIVOT SQL 查询
【发布时间】:2019-11-03 01:36:48
【问题描述】:

如果我有一张这样的桌子:

CREATE TABLE Students
(
    Id INT PRIMARY KEY IDENTITY,
    StudentName VARCHAR (50),
    Math INT,
    English INT,
    History INT,
    Science INT
)
GO

还有一个unpivot 查询,例如:

SELECT StudentName, Course, Score
FROM Students
UNPIVOT
(
    Score
    FOR Course in (Math, English, History, Science)
) AS SchoolUnpivot

最佳索引是什么样的?

【问题讨论】:

    标签: sql-server indexing query-optimization


    【解决方案1】:

    我将 1.000.000 个测试数据填充到 Students 表中,然后开始测试以下查询;

    注意不要在生产环境中使用DBCC DROPCLEANBUFFERS 语句。

    测试环境:

    Microsoft SQL Server 2019 (RC1) - 15.0.1900.25 (X64) 2019 年 8 月 16 日 14:20:53 版权所有 (C) 2019 Microsoft Corporation Developer Edition (64 位)Windows 10 Pro 10.0(内部版本 17763:)

    测试 1:

    以下查询需要 34 秒

    DBCC DROPCLEANBUFFERS
    GO
     SELECT StudentName, Course, Score
    FROM Students
     CROSS APPLY (
        VALUES 
            ('Math', Math),
            ('English', English),
            ('History', History),
            ('Science', Science)
        ) x(Course, Score)
    WHERE Score IS NOT NULL
    
    OPTION (MAXDOP 1)
    

    测试 2:
    以下查询需要 40 秒

    DBCC DROPCLEANBUFFERS
    GO
     SELECT StudentName, Course, Score
    FROM Students
     CROSS APPLY (
        VALUES 
            ('Math', Math),
            ('English', English),
            ('History', History),
            ('Science', Science)
        ) x(Course, Score)
    WHERE Score IS NOT NULL
    
    OPTION (MAXDOP 1)
    

    测试 3:

    以下查询在创建索引后需要 32 秒,执行计划也使用执行计划中创建的索引。

       CREATE NONCLUSTERED INDEX [PerformanceIndex] ON [dbo].[Students]
    (
        [Id] ASC,
        [Math] ASC,
        [English] ASC,
        [History] ASC,
        [Science] ASC
    )
    INCLUDE([StudentName])
    GO
     DBCC DROPCLEANBUFFERS
     GO
    SELECT StudentName, Course, Score
    FROM Students
    UNPIVOT
    (
        Score
        FOR Course in (Math, English, History, Science)
    ) AS SchoolUnpivo
    
    OPTION (MAXDOP 1)
    

    因此,在非聚集索引中使用 unpivot 列有助于我们提高查询性能,尤其是在这种情况下。

    【讨论】:

    • 谢谢,这就是我要找的!
    【解决方案2】:

    我不确定可以使用哪些索引来优化查询。需要查看查询的执行计划才能提出有根据的建议。

    但在进行索引之前,您可以尝试优化查询。提高性能的一种选择是使用 CROSS APPLY VALUES 而不是 UNPIVOTfollowing blog article 详细介绍了它可以提供的性能改进。

    因此,考虑以下查询:

    SELECT StudentName, Course, Score
    FROM Students
     CROSS APPLY (
        VALUES 
            ('Math', Math),
            ('English', English),
            ('History', History),
            ('Science', Science)
        ) x(Course, Score)
    WHERE Score IS NOT NULL
    

    我很想知道您是否获得了与博客作者报告的相同的性能优势。

    【讨论】:

      猜你喜欢
      • 2013-12-02
      • 2012-07-09
      • 1970-01-01
      • 2017-11-14
      • 1970-01-01
      • 2016-07-14
      • 1970-01-01
      • 2018-08-10
      • 1970-01-01
      相关资源
      最近更新 更多