【发布时间】:2019-04-19 13:09:38
【问题描述】:
我有一个非常慢的查询,如下所示:
SELECT *
FROM (
SELECT ..., nn_key_fast(nachname) nnk, ...
FROM t1
JOIN t2 ON
...
JOIN t3 ON
...
JOIN t4 ON
...
WHERE ...
AND t4.POSTCODE='1234'
)
WHERE ... AND nnk LIKE "N%"
现在,内部选择大约需要 2 分钟。如果我删除最后一个 WHERE 子句(t4.POSTCODE),它会在 ~4 秒内执行。没有这个子句的结果将是
所以,我的想法是:将该子句移到外部 SELECT,然后它只会应用于生成的
但是没有。查询花费的时间完全一样,所以要清楚:
SELECT *
FROM (
SELECT .....
FROM t1
JOIN t2 ON
...
JOIN t3 ON
...
JOIN t4 ON
...
WHERE ...
)
WHERE ...
AND POSTCODE='1234'
与第一个版本一样需要 2 分钟。
这对我来说似乎很疯狂。
直观地说,这必须由查询优化器执行,如下所示: 从内部选择创建一个表,如下所示:
CREATE TABLE res_from_inner AS (
SELECT .....
FROM t1
JOIN t2 ON
...
JOIN t3 ON
...
JOIN t4 ON
...
WHERE ...
)
...然后只在这个表上做外部选择,像这样:
SELECT *
FROM res_from_inner
WHERE POSTCODE='1234'
如果我手动执行此操作,则 CREATE TABLE 查询需要大约 4 秒,而第二个 SELECT 需要,如预期的那样
这怎么可能,怎么办?
【问题讨论】:
-
我猜你的索引中没有包含邮政编码。
-
子查询的 select 子句中有什么 -->
SELECT .....?如果您在 SELECT 子句中使用任何函数或表达式(如to_char( x ) as y或x+y as z),然后您在 WHERE 子句中使用其结果(如y = '123' or z=22,那么 Oracle 无法将谓词下推到子查询、索引没用,而且一定很慢。没有详细信息,很难在这里提出任何建议,请显示完整的查询,它是execution plan,现在我投票结束你的问题,因为它太宽泛了。 -
@krokodilko:现在感觉有点傻……你说得对,select子句中有一个函数,计算的字段用在外层select中。但是,当我执行整个查询时,今天需要 13 秒...但是:如果我从该选择创建一个表(创建表为...),则再次需要 2 分钟。结果集中只有大约 1000 条记录。抱歉让您感到困惑,我不确定自己到底在问什么。
标签: sql oracle subquery oracle10g query-optimization