【发布时间】: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% 以上。如果您将其放入答案中,我会将其标记为解决方案
标签: sql sql-server performance sql-tuning