我会有这样的查询:
select order_number, cart_value, is_Europe from (
select order_number, sum(product_values) as cart_value, max(is_EUR) as is_Europe
from products
group by order_number
) ordervalues
where is_Europe = 1
Run Code Online (Sandbox Code Playgroud)
注意最后一行。
假设子查询返回 30 行,其中 15 行的 is_Europe 为“1”,另一个为“0”。换句话说,花生。
但是...添加最后一行使查询从 20 秒变为 3+ 分钟并计数。将它嵌套在许多子查询中。
现在,我想我理解了 SQL 逻辑,因为它首先运行子查询,并且……一个微不足道的 where 语句……过滤 30 行……需要几纳秒。但不是与甲骨文。
这里发生了什么?
20 秒给我完整的结果集,然后只需隐藏带有“1”或“0”(无论我选择哪个)的行——这似乎是一项不可能完成的任务。
这是来自 PLSQL 的执行计划/解释计划。请注意,实际上,查询非常复杂,包含等级、组等......嵌套子查询......但是最后的事情需要 20 秒,最后的 append where 语句(即使提升了一个新的级别)打破了它......
实际上它更复杂(除了我的问题,它应该在子查询之后运行并过滤 30 行,对吗?实际上......结构类似于大陆(EUR,NA,ASIA)和一个函数调用 max (decode continent, 'EUR', 1,0) as Is_EUR group by order_id。大洲是一个例子,它实际上是一些随机维度。它确定订单是否曾经“欧洲”或其他什么。这是最快的方式包括“是”和“否”。我想我可以在这里重写查询,只是很难定期更改。为什么 Oracle 不简单地听取常识?
你没有抓住重点。查询优化是一项非常困难和微妙的工作。当面对复杂的查询时,优化器必须在数百万和数十亿的可能计划之间做出决定并找到最佳计划。所有这一切都在很短的时间内完成。
这个过程并不总是产生绝对最好的计划。只有一个优化器在短时间内认为它足够好。它可能是最好的,也可能是非常好的,也可能是糟糕的。
即使只添加一个 WHERE 条件,更改(复杂)查询也会使查询变得不同。现在优化器必须在数百万和数十亿计划之间进行选择,其中许多计划与以前不同。因此,在某些情况下,完全不同的计划和访问路径被确定为最佳。
再次选择的计划可能是绝对最好的,只是足够好或很糟糕。因此,即使复杂查询中的微小更改也可能导致完全不同的性能。好得多或更糟。通常 Oracle 优化器的工作非常好,因此在很小的更改后性能发生剧烈变化的情况很少见。
但是没有办法总能找到最好的计划,没有一直存在的时间限制。如果我们让它通过所有可能的计划并拥有 100% 准确的信息(统计数据等),它总是会产生最好的计划,但我们将不得不等待数小时、数天甚至数年的查询;)