具有多个连接的慢查询

时间:2014-11-17 21:04:30

标签: sql oracle oracle10g

我有以下查询,我正在尝试优化,如果我从下面的查询中删除连接条件 I.ident_id(从MISSING_Images miss中选择distinct(ident_id)),查询将在3秒内运行但有了这个,我需要3分钟来执行。

SELECT IDENT_ID
   FROM tbl_IDENT I
            JOIN tbl_TA AN ON (AN.IDENT_ID = I.IDENT_ID and AN.anchor_point = I.c_id)
            JOIN tbl_AB A ON (A.A_ID = I.A_ID)
            JOIN tbl_FULL_ARCHIVE FT ON (FT.ARCHIVE_ID = I.ARCHIVE_ID)
            WHERE (I.DATA_STATUS = 'ACTIVE' or I.DATA_STATUS = 'INACTIVE')
            AND 
            (
             I.FD = 'Y'
                OR


 I.ident_id in (select distinct(ident_id) from MISSING_Images miss where substr(miss.NAME, 0, INSTR(miss.NAME, '.',-1,1)) in (SELECT substr(IMG_NAME, 0, INSTR(IMG_NAME, '.',-1,1)) FROM IMAGES ))

);

从MISSING_Images miss 中选择distinct(ident_id)返回2000条记录,主tbl_IDENT有超过100,000条记录。我在I.ident_id上创建了索引

任何暗示如何改进它。我正在使用oracle 10g。

4 个答案:

答案 0 :(得分:2)

您可以尝试替换

I.ident_id in (select distinct(ident_id) from MISSING_Images miss)

EXISTS (select 1 from MISSING_Images miss where miss.ident_id = I.ident_id)

在MISSING_Images.ident_id

上创建一个索引

编辑:最直接的解决方案是:

EXISTS (select 1 from MISSING_Images miss 
        where miss.ident_id = I.ident_id
          and exists (select 1 from images img 
                      where substr(img.IMG_NAME, 0, INSTR(img.IMG_NAME, '.',-1,1))
                            = substr(miss,NAME, 0, INSTR(IMG_NAME, '.',-1,1))
                     )
        )

创建基于索引的索引:

create index indx_name1 on images(substr(IMG_NAME, 0, INSTR(IMG_NAME, '.',-1,1))); 
create index indx_name2 on MISSING_Images(substr(miss.NAME, 0, INSTR(miss.NAME, '.',-1,1))); 

请注意,此类索引会对未定义对象的插入/更新操作产生不良影响,并且需要一些额外空间。除此之外,它们不适用于空值。

其他选择:

EXISTS (select 1 from MISSING_Images miss join images img 
                        on substr(img.IMG_NAME, 0, INSTR(img.IMG_NAME, '.',-1,1))
                            = substr(miss,NAME, 0, INSTR(IMG_NAME, '.',-1,1))
        where miss.ident_id = I.ident_id
       )


EXISTS (select 1 from (select miss.ident_id MISSING_Images miss join images img 
                        on substr(img.IMG_NAME, 0, INSTR(img.IMG_NAME, '.',-1,1))
                            = substr(miss,NAME, 0, INSTR(IMG_NAME, '.',-1,1))
                       ) sub        
        where sub.ident_id = I.ident_id
       )

答案 1 :(得分:1)

尝试使用联合,首先使用?

SELECT IDENT_ID
FROM tbl_IDENT I
    JOIN tbl_TA AN ON AN.IDENT_ID = I.IDENT_ID AND AN.anchor_point = I.c_id
    JOIN tbl_AB A ON A.A_ID = I.A_ID
    JOIN tbl_FULL_ARCHIVE FT ON FT.ARCHIVE_ID = I.ARCHIVE_ID
WHERE 
    (I.DATA_STATUS = 'ACTIVE' OR I.DATA_STATUS = 'INACTIVE')
AND I.FD = 'Y'
UNION
SELECT IDENT_ID
FROM tbl_IDENT I
    JOIN tbl_TA AN ON AN.IDENT_ID = I.IDENT_ID AND AN.anchor_point = I.c_id
    JOIN tbl_AB A ON A.A_ID = I.A_ID
    JOIN tbl_FULL_ARCHIVE FT ON FT.ARCHIVE_ID = I.ARCHIVE_ID
    JOIN MISSING_Images miss ON I.ident_id = miss.ident_id
WHERE 
    I.DATA_STATUS = 'ACTIVE' 
OR I.DATA_STATUS = 'INACTIVE'
;

肯定可以提供更多改进,但为此,我需要查询的解释计划...

答案 2 :(得分:1)

MISSING_Images(ident_id)上创建索引。

我还建议您将where子句写为:

        WHERE I.DATA_STATUS IN ('ACTIVE', 'INACTIVE') AND
              (I.FD = 'Y' OR
               I.ident_id in (select ident_id from MISSING_Images miss)
              )

distinct子查询中不需要in。此外,in更容易阅读(和编写和维护),然后是单个比较的列表。该指数应该考虑到绩效。

答案 3 :(得分:0)

您甚至可以在连接条件中组合where过滤器 如下所示

SELECT IDENT_ID
   FROM tbl_IDENT I
            JOIN tbl_TA AN ON (AN.IDENT_ID = I.IDENT_ID and AN.anchor_point = I.c_id)
            and I.DATA_STATUS IN ('ACTIVE', 'INACTIVE') AND
            I.FD = 'Y'
                OR
             I.ident_id in (select distinct(ident_id) from MISSING_Images miss)
            JOIN tbl_AB A ON (A.A_ID = I.A_ID)
            JOIN tbl_FULL_ARCHIVE FT ON (FT.ARCHIVE_ID = I.ARCHIVE_ID);

甚至你可以使用exists子句(如@Multisync所说)可能会带来更好的性能。