繁体   English   中英

DB2的SQL优化

[英]SQL Optimization for DB2

如果您在两个结果集上执行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语句将使用一小部分主记录,而不必执行过滤主表两次,就像它可能在上面的例子中做的那样。

提前谢谢你,不管你有什么建议。

也许常见的表表达式有助于:

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的中间结果(仍然)非常大(几百万)那么这可能没有帮助。

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

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

一般来说,如果可以使用单个SQL语句完成任务,这将是完成任务的最快方法,那么创建临时表不太可能有益于性能。

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

但是,如果问题是性能,那么考虑在master(col, col2, col3)上放置一个索引。 这将加速查询的两个部分。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM