优化广泛使用 IN 子句的 Oracle SQL 查询

Posted

技术标签:

【中文标题】优化广泛使用 IN 子句的 Oracle SQL 查询【英文标题】:Optimizing an Oracle SQL query which uses IN clause extensively 【发布时间】:2015-01-12 12:46:15 【问题描述】:

我维护了一个应用程序,我在其中尝试优化使用多个 IN 子句的 Oracle SQL 查询。这个查询现在是一个阻塞器,因为它占用了将近 3 分钟的执行时间并且严重影响了应用程序的性能。这个查询是从 Java 代码(JDBC)调用的,看起来像这样:

Select disctinct col1,col2,col3,.. colN from Table1
where 1=1 and not(col1 in (idsetone1,idsetone2,... idsetoneN)) or
(col1 in(idsettwo1,idsettwo2,...idsettwoN))....
(col1 in(idsetN1,idsetN2,...idsetNN))

ID 集是从不同的架构中检索的,因此无法在表 1 的 column1 和 ID 集之间进行 JOIN。随着应用程序的使用,ID 集随着时间的推移而增长,目前它们的记录数超过 10,000 条。

如何开始优化此查询?

【问题讨论】:

为什么要使用多个in 子句?它们都在同一列。将列表合并为一个列表。 如果你使用NOT INOR 需要时间,因此尽量避免像 Gordon Linoff 所说的那样 @GordonLinoff Oracle 在列表中最多接受 1000 个元素。 “不同的架构”到底是什么意思?显然,可以连接来自不同模式的表:from schema1.table1 join schema2.tabl2... asktom.oracle.com/pls/asktom/… 【参考方案1】:

我真的很怀疑“ID 集是从不同的架构中检索的,因此无法在表 1 的 column1 和 ID 集之间进行 JOIN。”当然,您可以加入这些表,前提是您有选择权限。

无论如何,让我们假设由于某种原因这是不可能的。一种解决方案是先将所有条目插入到嵌套表中,然后使用这个:

CREATE OR REPLACE TYPE NUMBER_TABLE_TYPE AS TABLE OF NUMBER;

Select disctinct col1,col2,col3,.. colN from Table1
where 1=1 
   and not (col1 NOT MEMBER OF (NUMBER_TABLE_TYPE(idsetone1,idsetone2,... idsetoneN)) 
      OR
      (col1 MEMBER OF NUMBER_TABLE_TYPE(idsettwo1,idsettwo2,...idsettwoN))

关于最大值。 number of elements Oracle Documentation 说:因为嵌套表没有声明的大小,您可以在构造函数中放置 尽可能多的元素根据需要。 em>

我不知道你能把这句话当回事。

【讨论】:

您应该准备带有绑定变量 MEMBER OF :1 的语句,并使用 JDBC 直接构造嵌套表并将其放入其中 - 它将被流式传输到数据库而您没有构建/解析巨大的 SELECT-Strings。它会非常快! 仅供参考 - 你拼错了 DISTINCT,但我看到这是来自 OP【参考方案2】:

您应该将所有项目放入一个临时表并显式连接:

Select your cols
from Table1
left join table_with_items 
 on table_with_items.id = Table1.col1
where table_with_items.id is null;

另外,distinct 表明您的业务逻辑或应用程序架构存在问题。为什么你有重复的ID?你应该摆脱那个独特的。

【讨论】:

在 Oracle 中使用WHERE NOT EXISTS 而不是外连接不匹配查询可能会更好。

以上是关于优化广泛使用 IN 子句的 Oracle SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

我可以使用Java代码在sql语句(Oracle)的IN子句中传递字符串列表吗

oracle数组 拼到sql的in子句中去

列举sql优化都有哪些方式方法 博客园

Oracle SQL 性能优化技巧

Sql server not in优化

带有 IN 子句的 SQL 查询的 MYSQL 查询优化