如何优化此嵌套的SQL SELECT查询

时间:2019-04-19 13:09:39

标签: sql oracle subquery oracle10g query-optimization

我有一个非常慢的查询,看起来像这样:

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秒内执行。没有此子句的结果将是<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秒钟。

这怎么可能,怎么办?

2 个答案:

答案 0 :(得分:1)

您必须查看执行计划以了解实际情况。情况正在改变。

您可以尝试的一件事是CTE:

with s as (
      <subquery here>
     )
select s.*
from s
where . . .;

Oracle可能会自动实现。或者您可以给出提示:

with s as (
      select /*+ materialize */ . . .
      . . .
     )
select s.*
from s
where . . .;

答案 1 :(得分:1)

我尝试远离嵌套的select语句。在这种情况下,我会将内部的select语句作为子查询,然后从中选择想要的内容。

,子查询为(   从...中选择...加入...加入...加入... )

从子查询中选择*

-希望有帮助:]