我有以下查询,我正在尝试优化,如果我从下面的查询中删除连接条件 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。
答案 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所说)可能会带来更好的性能。