索引以外的 SQL Server 调优建议

Posted

技术标签:

【中文标题】索引以外的 SQL Server 调优建议【英文标题】:SQL Server tuning recommendations beyond indexing 【发布时间】:2018-11-28 15:41:53 【问题描述】:

我正在处理一个 SQL 查询,该查询需要许多自连接表来创建聚合函数,如下所示。

SELECT  
    tab1.foo, 
    tab1.bar, 
    tab1.baz, 
    tab1.bam/tab2.bam as bam_ratio, 
    RANK() OVER (PARTITION BY tab1.bar, tab1.baz ORDER BY tab1.foo DESC) RANK
FROM 
    (SELECT 
         foo, 
         bar, 
         baz, 
         bam
     FROM 
         OPENDATASOURCE(server).dbo.table1
     WHERE 
         qux = 1 AND quux = 'A' AND corge = 2) tab1
JOIN
    (SELECT 
         foo, 
         bar, 
         baz, 
         bam
     FROM 
         OPENDATASOURCE(server).dbo.table1
     WHERE 
         qux = 1 AND quux = 'B' AND corge = 2) tab2 ON tab1.bar = tab2.bar
                                                    AND tab1.baz = tab2.baz
                                                    AND tab1.foo = tab2.foo

问题是这些表中的每一个都只有几列但有数千万条记录。这造成了一个独特的情况,即索引不能充分提高性能(上面的查询使用 table1 中的每一行)。

我注意到的是,这些表调用往往只在一两个次要方面发生变化,例如示例中的 quux,并且它们没有需要使用比必要行更多的主键,这对索引没有帮助并且似乎是多余的。

除了简单的索引之外,还有其他方法可以提高性能吗?我愿意更改基础表并创建孤立表。

【问题讨论】:

简单的第一步是将 OPENDATASOURCE 查询中的记录删除到临时表中,然后加入 TEMP。这将允许您在临时表上应用索引(在插入之后),但即使不添加索引,也可能仍然比您当前的派生表更快。 可以把执行计划放在这里吗?此外,您可以获得的主要收益是在源框上执行它并在您正在执行查询的框上读取它。 您声明这些表没有主键。不是一个好主意,但他们有聚集索引吗?如果不是这样,您正在处理堆,无论您做什么,性能都会很糟糕。 @scsimon 是的,这就是我的想法,我会试试这个,看看它如何影响结果。 @scsimon 我没有向临时表添加索引,而是编辑了当前索引并制作了可以减少 OPENDATASOURCE 查询的临时表。这将性能提高了 99% 以上。如果您将其放入答案中,我会将其标记为解决方案 【参考方案1】:

您可以改进的一个性能问题是跨服务器加入。 OPENROWSET、链接服务器等会发生这种情况。

缓解它的最简单方法是将数据从远程数据源提取到临时表或临时表中。这会将数据本地存储在 tempdb 中。然后,加入临时表。 SQL Server 会自动为这些表创建统计信息,这将大大提高您的性能,而且数据是本地的,但如果您愿意,您也可以添加索引来加快连接速度。

【讨论】:

减少 OPENROWSET 将查询的性能提高了 99.96%。很好的收获!

以上是关于索引以外的 SQL Server 调优建议的主要内容,如果未能解决你的问题,请参考以下文章

TELEDB分片建议

Oracle 查询调优建议

SQL Server 2005,维护计划建议

在SQL Server中为啥不建议使用Not In子查询

Sql server 千万级大数据SQL查询优化的几点建议

译索引进阶(十七): SQL SERVER索引最佳实践