我有一个非常慢的查询,如下所示:
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),它将在~4secs中执行。没有这个子句的结果将是<1000条记录,所以这是一个非常小的集合。
所以,我的想法是:将该子句移动到外部SELECT,然后它将仅应用于生成的<1000条记录。
但不是。查询完全一样长,所以要清楚:
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需要,如预期的那样<1秒。
这怎么可能,怎么做呢?
你必须查看执行计划才能看到真正发生的事情。事情正在发生变化。
您可能尝试的一件事是CTE:
with s as (
<subquery here>
)
select s.*
from s
where . . .;
Oracle可能会自动实现这一点。或者你可以给一个提示:
with s as (
select /*+ materialize */ . . .
. . .
)
select s.*
from s
where . . .;
我试图远离嵌套的select语句。在这种情况下,我将内部select语句作为子查询,然后从中选择我想要的。
子查询为(select ... from ... join ... join ... join ... where)
从子查询中选择*
- 希望有助于:]