osc*_*tin 4 subquery oracle10g
由于各种原因,我无法粘贴整个SQL,因此请考虑以下示例:
select *
from
(select nvl(get_quantity(1), 10) available_qty
from dual)
where available_qty > 30;
Run Code Online (Sandbox Code Playgroud)
get_quantity是一个函数,它根据传递给它的记录的ID进行计算.如果它返回null,我用nvl()它强制它为10.
当我在父查询中使用WHERE子句时,查询运行速度非常慢.WHERE然而,当我注释掉该条款时,它运行得非常快.我没有得到的是为什么它可以非常快速地显示数据,但它不能以同样快的速度查询它.我也在询问子查询的结果.我的印象是子查询返回"渲染"数据集.这几乎就像查询available_qty标识符导致它引用子查询中的内容一样.
这就是为什么我不认为get_quantity函数的内容在这里是相关的,所以我没有打扰它.相反,我认为这是我对Oracle如何处理子查询等等的误解.
你们中的任何一位甲骨文大师都知道我做错了什么吗?
事后补充:当我输入这个问题的标签时,标签"相关子查询"出现了.在进行一些快速研究时,似乎这种类型的子查询在某种程度上取决于外部查询.这可能与我的问题有关吗?
我们来试试吧.首先,我们将运行以下查询:
select lvl, rnd
from (select level as lvl from dual connect by level <= 5) a,
(select dbms_random.value() rnd from dual) b;
Run Code Online (Sandbox Code Playgroud)
"a"子查询将返回5行,其值为1到5."b"子查询将返回一行随机值.如果在两个表连接之前运行该函数(通过笛卡尔坐标),则将为每一行返回相同的随机值.实际结果:
LVL RND
---------- ----------
1 .417932089
2 .963531718
3 .617016889
4 .128395638
5 .069405568
5 rows selected.
Run Code Online (Sandbox Code Playgroud)
显然,该函数是针对每个连接的行运行的,而不是针对连接之前的子查询运行的.这是Oracle优化器决定查询的最佳路径是按该顺序执行操作的结果.为了防止这种情况,我们必须在第二个子查询中添加一些东西,这将使Oracle在执行连接之前完整地运行子查询.我们将rownum添加到子查询中,因为Oracle知道rownum如果在连接之后运行则会改变.以下查询演示了这一点:
select lvl, rnd from (
select level as lvl from dual connect by level <= 5) a,
(select dbms_random.value() rnd, rownum from dual) b;
Run Code Online (Sandbox Code Playgroud)
从结果中可以看出,在这种情况下,该函数只运行一次:
LVL RND
---------- ----------
1 .028513902
2 .028513902
3 .028513902
4 .028513902
5 .028513902
5 rows selected.
Run Code Online (Sandbox Code Playgroud)
根据你的情况,这很可能是由所提供的过滤器where子句使优化走不同的路,在那里的重复运行的功能,而不是一次.通过使Oracle以编写的方式运行子查询,您应该获得更一致的运行时间.