sql - Oracle - 像文本宏一样使用 WITH 子句
问题描述
我有一个 SQL 查询,它在联合的两个不同位置重用一个复杂的子查询
SELECT A.PROJECT_ID, B.INFO B.MORE_INFO
FROM A
INNER JOIN (
-- Complex subquery
) B ON A.PROJECT_ID = B.PROJECT_ID
WHERE -- Filter to a disjoint subset --
UNION
SELECT C.PROJECT_ID, B.INFO B.MORE_INFO
FROM C
INNER JOIN (
-- SAME Complex subquery
) B ON C.PROJECT_ID = B.PROJECT_ID
WHERE -- Filter to a disjoint subset --
为了减少重复代码,我想使用 WITH 子句,所以我只需要编写一次复杂的子查询。
WITH B AS (
-- Complex subquery
)
SELECT A.PROJECT_ID, B.INFO B.MORE_INFO
FROM A
INNER JOIN B ON A.PROJECT_ID = B.PROJECT_ID
WHERE -- Filter to a disjoint subset --
UNION
SELECT C.PROJECT_ID, B.INFO B.MORE_INFO
FROM C
INNER JOIN B ON A.PROJECT_ID = B.PROJECT_ID
WHERE -- Filter to a disjoint subset --
这可行,但现在查询需要 4 倍的时间来执行。查看这两个查询的解释计划,我想我知道发生了什么: WITH 子句正在创建一个没有索引的临时表,因此在连接 A 和 B 时,正在执行全表扫描。在原始查询的计划中,使用了下推谓词,从而减少了连接所需的工作。这与我发现的这篇现代 SQL 文章证实了这一点,该文章讨论了 WITH 子句如何对性能产生不利影响。
考虑到这一切,有没有一种方法可以让我使用 WITH 子句更像是 C 预处理器中的文本宏而不创建临时表?也许有一个我可以使用的计划提示?还是 Oracle 或 SQL 中可能有其他本机功能允许我做同样的事情?
最后,我希望看到 Oracle 执行与原始查询相同的计划,同时还利用 WITH 子句提供的代码模块化
一些注意事项:
- 甲骨文 12c
- 我无法消除 UNION
- 两个 WHERE 过滤器不同,导致两个不相交的集合
解决方案
您可以尝试的最简单的方法是inline
提示。
唉,由于某种我个人不明白的原因,这个提示没有记录(与它的对应部分相同,materialize
提示),即使它们被广泛使用。根据您组织的规则,您可能会也可能无法使用此解决方案。我假设您知道提示,但不知道这个特定的提示;如果您需要更多帮助,请说出来。无论如何,您可能想在测试环境中尝试一下,看看可以做什么。
编辑(因为其他人也可能读到这个):
该with
子句应如下所示:
with
b as ( select /*+ inline */ ...... complex query ....... )
.......
推荐阅读
- javascript - 用画布反应问题 - 错误计算鼠标的位置
- tomcat - 如何解决检测到的 xampp tomcat 问题?
- typescript - 带有签名的打字稿箭头函数接受错误的参数
- discord - 为什么我的调平系统不起作用。当我将它移入齿轮时它停止工作
- javascript - 如何使用左右箭头制作圆形效果?
- class - Groovy:字段中不允许进行多个分配
- github - 如何制作版本的 repo 并可以查看和下载旧版本的 github repo
- python - 如何在 SQL-LIMIT 中传递动态值?
- vb.net - 如何获取多行文本框每行的长度并检查多于或少于 VB .NET 中的特定值
- sql - PostgreSql 3 个表的右连接