0

如果您遇到对两个结果集执行 Union All 的情况,并且每个结果集都是从具有主表的相同过滤子集的内部联接派生的,那么查询引擎是否会“命中”主表一次,或者两次?

例子:

SELECT m.col4, st1.col2
FROM master m
     INNER JOIN subTable1 st1
     on st1.col1 = m.col1
     WHERE m.col1 = 'a' and m.col2 = 123 and m.col3 = "a1b2"
UNION ALL
SELECT m.col4, st2.col2
FROM master m
     INNER JOIN subTable2 st2
     on st2.col1 = m.col1
     WHERE m.col1 = 'a' and m.col2 = 123 and m.col3 = "a1b2"

我正在尝试确定创建一个临时表来保存主表的过滤结果是否有益,因此 UNION ALL 语句将使用主记录的一小部分,而不必执行过滤主表两次,就像上面的例子中可能做的那样。

提前感谢您提供的任何建议。

4

3 回答 3

1

也许一个通用的表表达式会有所帮助:

with small_master as (
   select m.col4,
          m.col1
   from master
   where m.col1 = 'a' 
     and m.col2 = 123 
     and m.col3 = 'a1b2'
)
SELECT m.col4, st1.col2
FROM small_master m
     INNER JOIN subTable1 st1
     on st1.col1 = m.col1
UNION ALL
SELECT m.col4, st2.col2
FROM small_master m
     INNER JOIN subTable2 st2
     on st2.col1 = m.col1;

根据我的经验(虽然不是使用 DB2),如果 CTE 大幅减少行数(比如从“数百万”到“数千”),这会有所帮助。

如果 CTE 的中间结果(仍然)很大(几百万),那么这可能无济于事。

但只有执行计划才能说明这一点。

于 2013-05-13T15:28:14.853 回答
1

回答这类“假设”问题的最简单方法是查看查询计划。您可以使用命令轻松生成一个db2expln -d <your db> -f <your query file> -z <your query delimiter> -gi

一般来说,如果一个任务可以用一条 SQL 语句完成,那将是完成任务的最快方式,所以创建临时表不太可能提高性能。

于 2013-05-13T18:09:15.500 回答
0

这在很大程度上取决于数据库和所涉及的表的统计信息。我对 DB2 不是很熟悉。

但是,如果问题是性能,那么考虑在master(col, col2, col3). 这将加快查询的两个部分。

将 CTE 用作临时表是高度特定于数据库的。Postgres 总是实例化 CTE,所以代码只运行一次。SQL Server 从不这样做。我不知道 DB2 在这方面的行为。但是,我更愿意添加索引来显式提高性能,而不是摆弄查询——您的新查询可能会导致基于表统计信息更改、新软件发布或硬件升级时的意外查询计划。

作为 SQL Server 行为的参考,您可能对这个这个这个讨论感兴趣。

于 2013-05-13T15:39:12.747 回答