使用 EXISTS 指令是否改进了这个查询
Does using EXISTS instruction improves this query
我正在学习如何改进我的一些查询,例如,我看到使用 EXISTS 而不是 IN 效果更好,所以我做了以下修改,但我不能 100% 确定我是否通过使用 EXISTS 获得了我期望的相同结果, 到目前为止,当我在不同的时期执行时,它给了我相同的结果,但我仍然怀疑,如果它确实存在更好的性能以及它是否做同样的事情,有人可以为我澄清吗?
VARIABLE periodo STRING;
SELECT MO.STRMOVANOMES,
C.STRCLINOMBRE,
MO.STRCLINIT,
MO.STROBLOBLIGSARC,
MO.NUMPROCODIGO,
MO.NUMMOVTIPOCREDITO,
MO.NUMMOVTIPOGARANTIA,
MO.STROBLMODALIDAD,
MO.NUMMOVCALIFICACION,
MO.NUMMOVVLRCAPCREDITO,
MO.NUMMOVVLRINTCREDI,
MO.NUMMOVVLRCAPOTRO
FROM TBLMOVOBLIGACIONES MO,
TBLCLIENTES C
WHERE MO.STRMOVANOMES = :periodo
AND C.STRCLITIPOID ='N'
AND MO.NUMMOVTIPOCREDITO = 2
AND MO.NUMPROCODIGO IN (1,3,4,5,6,7,10,15,16,18,24,29,32,38,40,43,44,45,49,51,54,55,56,70,71,72,73,74,75,76,77,78,81,82,83,84,85)--ALL APPLICATIONS
AND C.STRCLINIT=MO.STRCLINIT
AND SUBSTR(MO.STRCLINIT,1,9) >= 600000000
AND SUBSTR(MO.STRCLINIT,1,9) <= 999999999;
-- USING EXISTS
SELECT MO.STRMOVANOMES,
C.STRCLINOMBRE,
MO.STRCLINIT,
MO.STROBLOBLIGSARC,
MO.NUMPROCODIGO,
MO.NUMMOVTIPOCREDITO,
MO.NUMMOVTIPOGARANTIA,
MO.STROBLMODALIDAD,
MO.NUMMOVCALIFICACION,
MO.NUMMOVVLRCAPCREDITO,
MO.NUMMOVVLRINTCREDI,
MO.NUMMOVVLRCAPOTRO
FROM TBLMOVOBLIGACIONES MO,
TBLCLIENTES C
WHERE MO.STRMOVANOMES = :periodo
AND C.STRCLITIPOID ='N'
AND MO.NUMMOVTIPOCREDITO = 2
AND EXISTS (SELECT NUMPROCODIGO FROM TBLMOVOBLIGACIONES)--ALL APPLICATIONS
AND C.STRCLINIT=MO.STRCLINIT
AND SUBSTR(MO.STRCLINIT,1,9) >= 600000000
AND SUBSTR(MO.STRCLINIT,1,9) <= 999999999;
首先,一些一般信息
理论上,当需要根据值列表检查某个值时使用 IN 子句,因此数据库必须遍历列表以查找给定的值。而 EXIST 是让 db 执行快速查询(这是 db 设计的)以检查是否至少有一行。
如果您要检查的值列表在 table 中,通常最好使用 EXISTS。那是一些理论。
实际上,从版本 10(非常旧的版本)开始,Oracle 为 IN 和 EXISTS 查询构建了相同的执行计划,如果您需要更有经验的人,这里有一个很好的 explanation。
要检查它是否影响查询执行,请检查解释计划(google 为您的 dev-tool)并比较总体“成本”(成本比较并不总是一件好事, 不过这种情况没问题)
现在,回到您的查询。
只要 table TBLMOVOBLIGACIONES 至少有一行,您使用它的方式中的 EXISTS 将始终 return 为真。不确定这是否是您要查找的内容。
我相信你需要以这种方式使用它
AND EXISTS (SELECT 1 FROM TBLMOVOBLIGACIONES WHERE NUMPROCODIGO = MO.NUMPROCODIGO)
因此它将检查是否至少有一条记录连接到您在上一步中选择的数据。
我在这里看到的下一步是可以轻松地将 EXISTS 子句转换为常规 table 连接,因此您可以编写以下内容而不是在 IN 或 EXISTS 之间进行选择
FROM TBLMOVOBLIGACIONES MO,
TBLCLIENTES C,
TBLMOVOBLIGACIONES M
WHERE MO.STRMOVANOMES = :periodo
AND C.STRCLITIPOID ='N'
AND MO.NUMMOVTIPOCREDITO = 2
AND M.NUMPROCODIGO = MO.NUMPROCODIGO--ALL APPLICATIONS
AND C.STRCLINIT=MO.STRCLINIT
AND SUBSTR(MO.STRCLINIT,1,9) >= 600000000
AND SUBSTR(MO.STRCLINIT,1,9) <= 999999999;
这是值得做的,因为连接总是更好的选择,允许数据库变化 table 连接排序以获得更好的性能。
我正在学习如何改进我的一些查询,例如,我看到使用 EXISTS 而不是 IN 效果更好,所以我做了以下修改,但我不能 100% 确定我是否通过使用 EXISTS 获得了我期望的相同结果, 到目前为止,当我在不同的时期执行时,它给了我相同的结果,但我仍然怀疑,如果它确实存在更好的性能以及它是否做同样的事情,有人可以为我澄清吗?
VARIABLE periodo STRING;
SELECT MO.STRMOVANOMES,
C.STRCLINOMBRE,
MO.STRCLINIT,
MO.STROBLOBLIGSARC,
MO.NUMPROCODIGO,
MO.NUMMOVTIPOCREDITO,
MO.NUMMOVTIPOGARANTIA,
MO.STROBLMODALIDAD,
MO.NUMMOVCALIFICACION,
MO.NUMMOVVLRCAPCREDITO,
MO.NUMMOVVLRINTCREDI,
MO.NUMMOVVLRCAPOTRO
FROM TBLMOVOBLIGACIONES MO,
TBLCLIENTES C
WHERE MO.STRMOVANOMES = :periodo
AND C.STRCLITIPOID ='N'
AND MO.NUMMOVTIPOCREDITO = 2
AND MO.NUMPROCODIGO IN (1,3,4,5,6,7,10,15,16,18,24,29,32,38,40,43,44,45,49,51,54,55,56,70,71,72,73,74,75,76,77,78,81,82,83,84,85)--ALL APPLICATIONS
AND C.STRCLINIT=MO.STRCLINIT
AND SUBSTR(MO.STRCLINIT,1,9) >= 600000000
AND SUBSTR(MO.STRCLINIT,1,9) <= 999999999;
-- USING EXISTS
SELECT MO.STRMOVANOMES,
C.STRCLINOMBRE,
MO.STRCLINIT,
MO.STROBLOBLIGSARC,
MO.NUMPROCODIGO,
MO.NUMMOVTIPOCREDITO,
MO.NUMMOVTIPOGARANTIA,
MO.STROBLMODALIDAD,
MO.NUMMOVCALIFICACION,
MO.NUMMOVVLRCAPCREDITO,
MO.NUMMOVVLRINTCREDI,
MO.NUMMOVVLRCAPOTRO
FROM TBLMOVOBLIGACIONES MO,
TBLCLIENTES C
WHERE MO.STRMOVANOMES = :periodo
AND C.STRCLITIPOID ='N'
AND MO.NUMMOVTIPOCREDITO = 2
AND EXISTS (SELECT NUMPROCODIGO FROM TBLMOVOBLIGACIONES)--ALL APPLICATIONS
AND C.STRCLINIT=MO.STRCLINIT
AND SUBSTR(MO.STRCLINIT,1,9) >= 600000000
AND SUBSTR(MO.STRCLINIT,1,9) <= 999999999;
首先,一些一般信息
理论上,当需要根据值列表检查某个值时使用 IN 子句,因此数据库必须遍历列表以查找给定的值。而 EXIST 是让 db 执行快速查询(这是 db 设计的)以检查是否至少有一行。
如果您要检查的值列表在 table 中,通常最好使用 EXISTS。那是一些理论。
实际上,从版本 10(非常旧的版本)开始,Oracle 为 IN 和 EXISTS 查询构建了相同的执行计划,如果您需要更有经验的人,这里有一个很好的 explanation。
要检查它是否影响查询执行,请检查解释计划(google 为您的 dev-tool)并比较总体“成本”(成本比较并不总是一件好事, 不过这种情况没问题)
现在,回到您的查询。 只要 table TBLMOVOBLIGACIONES 至少有一行,您使用它的方式中的 EXISTS 将始终 return 为真。不确定这是否是您要查找的内容。
我相信你需要以这种方式使用它
AND EXISTS (SELECT 1 FROM TBLMOVOBLIGACIONES WHERE NUMPROCODIGO = MO.NUMPROCODIGO)
因此它将检查是否至少有一条记录连接到您在上一步中选择的数据。
我在这里看到的下一步是可以轻松地将 EXISTS 子句转换为常规 table 连接,因此您可以编写以下内容而不是在 IN 或 EXISTS 之间进行选择
FROM TBLMOVOBLIGACIONES MO,
TBLCLIENTES C,
TBLMOVOBLIGACIONES M
WHERE MO.STRMOVANOMES = :periodo
AND C.STRCLITIPOID ='N'
AND MO.NUMMOVTIPOCREDITO = 2
AND M.NUMPROCODIGO = MO.NUMPROCODIGO--ALL APPLICATIONS
AND C.STRCLINIT=MO.STRCLINIT
AND SUBSTR(MO.STRCLINIT,1,9) >= 600000000
AND SUBSTR(MO.STRCLINIT,1,9) <= 999999999;
这是值得做的,因为连接总是更好的选择,允许数据库变化 table 连接排序以获得更好的性能。