Oracle 存储过程 - NOT IN (SUBQUERY) 消耗大量时间

Posted

技术标签:

【中文标题】Oracle 存储过程 - NOT IN (SUBQUERY) 消耗大量时间【英文标题】:Oracle Stored procedure - NOT IN (SUBQUERY) CONSUMES A LOT OF TIME 【发布时间】:2012-06-07 10:20:41 【问题描述】:

我有 Oracle 程序,它的工作与以下相同:

create or replace
PROCEDURE My_TEST_PROCEDURE
(
   cur out sys_refcursor
)
AS
BEGIN
  open cur for
   SELECT * FROM MYTABLE1
   WHERE MYTABLE1.SOMEROWNAME NOT IN 
        (SELECT SOMEROWNAME FROM MYTABLE2);
END My_TEST_PROCEDURE;

但这两张表的数据很多,每张大约有300000行。所以需要很长时间才能完成。我能做些什么来减少那段时间。我尝试声明一个 sys_refcursor 并将数据读入这个游标,如下所示:

create or replace
PROCEDURE My_TEST_PROCEDURE
(
   cur out sys_refcursor
)
IS
DECLARE EXISTING_ITEMS SYS_REFCURSOR;
BEGIN
  OPEN EXISTING_ITEMS FOR
    SELECT SOMEROWNAME FROM MYTABLE2;
  open cur for
   SELECT * FROM MYTABLE1
   WHERE MYTABLE1.SOMEROWNAME NOT IN 
        EXISTING_ITEMS;
END My_TEST_PROCEDURE;

但这一次发生了 ORA-00932 错误。我能做什么?

提前致谢。

【问题讨论】:

查询产生了多少条不匹配的记录? “充足的时间”是多长时间? 【参考方案1】:

使用如下的连接查询:

SELECT MYTABLE1.* 
FROM   MYTABLE1 
       left join MYTABLE2 
              ON MYTABLE1.SOMEROWNAME = MYTABLE2.SOMEROWNAME 
WHERE  MYTABLE2.SOMEROWNAME IS NULL 

【讨论】:

会有什么不同? 感谢您的快速回复。但我在 table2 中没有任何空数据。 mytable2 是一个日志文件,我在发送时将 myTable1 中的 ID-s 添加到日志表中,并且我想从 myTable1 中选择未发送的项目。我正在使用日志表,因为我不能在 myTable1 中添加另一列 MYTABLE2.SOMEROWNAME 对于 MyTable1 中没有匹配记录的行将有空数据。【参考方案2】:

避免使用*,指定列名。

您为什么使用光标?您正在做的事情可以使用 b.mycolumn 为空的左外连接来实现

最好的问候。

【讨论】:

以上是关于Oracle 存储过程 - NOT IN (SUBQUERY) 消耗大量时间的主要内容,如果未能解决你的问题,请参考以下文章

请问oracle怎么执行存储过程

Oracle如何创建存储过程和如何调用存储过程

oracle 存储过程中调用存储过程

oracle存储过程中循环调用存储过程

oracle中的存储过程怎么写

求两个oracle存储过程例子