Sql 多连接的慢速查询
我有下面的查询,我正在尝试优化,如果我从下面的查询中删除缺少的图片中的select DISTINCEDENT_id中的连接条件I.ident_id,查询将在3秒钟内运行,但执行此查询需要3分钟Sql 多连接的慢速查询,sql,oracle,oracle10g,Sql,Oracle,Oracle10g,我有下面的查询,我正在尝试优化,如果我从下面的查询中删除缺少的图片中的select DISTINCEDENT_id中的连接条件I.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
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 ))
)
从丢失的图像中选择Distincedent_id miss return 2000记录,主tbl_id有超过100000条记录。我已经在I.ident_id上创建了索引
任何关于如何改进它的提示。我正在使用oracle 10g。首先,尝试使用联合
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'
;
当然可以提供更多的改进,但为此我需要一个查询的解释计划…首先尝试一个联合
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'
;
当然可以提供更多的改进,但为此我需要一个查询的解释计划…您可以尝试替换
I.ident_id in (select distinct(ident_id) from MISSING_Images miss)
与
并在缺少的图像上创建索引。ident\u 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)));
请注意,此类索引可能会对不存在的对象上的插入/更新操作产生不良影响,并需要一些额外的空间。除此之外,它们不能很好地处理null
其他选择:
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
)
你可以试着替换
I.ident_id in (select distinct(ident_id) from MISSING_Images miss)
与
并在缺少的图像上创建索引。ident\u 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)));
请注意,此类索引可能会对不存在的对象上的插入/更新操作产生不良影响,并需要一些额外的空间。除此之外,它们不能很好地处理null
其他选择:
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
)
在缺少的\u Imagesident\u 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)
)
在in子查询中不需要distinct。此外,in更易于读写和维护,然后是一个单独比较的列表。索引应考虑性能。针对缺少的\u Imagesident\u 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)
)
在in子查询中不需要distinct。此外,in更易于读写和维护,然后是一个单独比较的列表。索引应该考虑性能。您甚至可以在连接条件中组合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所说的,这可能会导致更好的性能。您甚至可以在连接条件中组合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所说的,这可能会导致更好的性能。我在DB2上看到一些基准测试,其中exists的性能优于in,因此我对Oracle上的情况也不会感到惊讶。也就是说,如果你没有关于MISSING_Images.ident_id的索引,那么创建该索引将有更大的改进。嗨,Mike,使用MISSING_Images.ident_id索引时,情况有所改善,但我更新了问题,因为我忘记在MISSING_Images中添加where子句,该子句使用substr,这似乎是一个实际问题。@atif您有多少图像?是否有可能将外键存储在MISSING_IMAGES中的图像上,而不是解析和比较名称?外键不可能,因为用户将它们上载到IMAGES表中,我们将它们重新处理到jpgs MISSING_IMAGES中,因此两个表中的扩展不同,这就是为什么我们通过名称检查它,而不使用图像扩展。大约有10000张图片。@atif我已经更新了我的答案。基于函数的索引是最明显的解决方案,但不一定是最好的。Insert/update可能有点慢,但它通常在实时系统中有很多Insert更新。我在DB2上见过一些基准测试,其中EXISTS的性能比in好,所以我对Oracle上的情况也不会感到惊讶。也就是说,如果你没有关于MISSING_Images.ident_id的索引,那么创建该索引将有更大的改进。嗨,Mike,使用MISSING_Images.ident_id索引时,情况有所改善,但我更新了问题,因为我忘记在MISSING_Images中添加where子句,该子句使用substr,这似乎是一个实际问题。@atif您有多少图像?是否有可能将外键存储在MISSING_IMAGES中的图像上,而不是解析和比较名称?外键不可能,因为用户将它们上载到IMAGES表中,我们将它们重新处理到jpgs MISSING_IMAGES中,因此两个表中的扩展不同,这就是为什么我们通过名称检查它,而不使用图像扩展。大约有10000张图片。@atif我已经更新了我的答案。基于函数的索引是最明显的解决方案,但不一定是最好的。插入/更新可能会稍微慢一点,但在具有大量插入更新的实时系统中通常是有意义的。