匿名PL / SQL块与Native SQL的性能

时间:2017-01-24 17:27:55

标签: sql oracle performance plsql locking

我有一个SQL语句,在PL / SQL块中执行时会产生明显不同的性能。

SQL非常简单。

INSERT into Existing_Table SELECT col1,col2... from Other_table where rownum < 100000

当它作为SQL执行时,它几乎立即返回。

但是当在Anonymous PL / SQL块中执行时,它会永远挂起:

begin
    INSERT into Existing_Table SELECT col1, col2... from Other_table where rownum < 100000;
end;
/

2 个答案:

答案 0 :(得分:2)

  

但是当在Anonymous PL / SQL块中执行时,它会永远挂起:

我猜两件事:

  1. 您的表(Existing_Table)对您在insert语句中使用的其中一列有约束。
  2. 您忘记在执行SQL语句和PL / SQL匿名阻止之间发出提交。
  3. 在SQL和PL / SQL中执行语句不应该在性能上有所不同。它应该在几乎相同的时间内执行。 但由于约束或提交,它被阻止,因为该行被锁定。

    这是一个例子。

    在第1节中,创建两个表。一个有约束,一个没有:

    create table Existing_Table 
    (
      existing_column number primary key
    );
    
    create table Existing_Table_2
    (
      existing_column number
    );    
    

    在同一会话中,执行以下SQL语句:

    insert into Existing_Table (existing_column) values (1);
    

    结果:

    1 row inserted.
    

    在另一个(会话2)上,执行以下PL / SQL匿名阻止:

    begin
      insert into Existing_Table (existing_column) values (1);
    end;
    

    这将挂起,直到您在会话1中发出提交。

    这是因为第1节已经&#34;保留&#34; &#34; 1&#34;的价值对于existing_column,将被&#34;保存&#34;当您发出提交时。 第2节仅仅是等待会话1提交或回滚插入。

    现在,当我回到会话1并发出提交时,该行将被解锁。 但是,由于完整性约束违规,会话2将导致错误:

    Error starting at line : 1 in command -
    begin
      insert into Existing_Table (existing_column) values (1);
    end;
    Error report -
    ORA-00001: unique constraint (APPS.SYS_C001730810) violated
    ORA-06512: at line 2
    00001. 00000 -  "unique constraint (%s.%s) violated"
    *Cause:    An UPDATE or INSERT statement attempted to insert a duplicate key.
               For Trusted Oracle configured in DBMS MAC mode, you may see
               this message if a duplicate entry exists at a different level.
    *Action:   Either remove the unique restriction or do not insert the key.
    

    现在,另一个没有约束的表的例子。

    在会话3中运行以下SQL而不提交:

    insert into Existing_Table_2 (existing_column) values (1);
    

    结果:

    1 row inserted.
    

    在会话4中的匿名PL / SQL块中运行相同的SQL:

    begin
      insert into Existing_Table_2 (existing_column) values (1);
    end;
    

    结果:

    PL/SQL procedure successfully completed.
    

    即使没有在会话1中提交,它也会插入正常,因为没有违反任何约束。

    请注意,在您发出提交之前,会话3和4中的所有数据都不会实际保存在数据库中。

    在此处查看有关会话阻止的其他文章:

    Tracking Oracle blocking sessions

    Find blocking sessions

答案 1 :(得分:0)

我试图重新创建问题,但无法解决。正如其他人正确指出的那样,SQL很简单并且执行它,因为SQL或者不是PL / SQL就不应该有所不同。

我唯一想到的是,我可能没有注意到是否有另一个会话在没有COMMIT / ROLLBACK的情况下尝试DML;这可能导致了悬念。所以BobC和Migs Isip提到的场景可能与此相关。谢谢大家。