sql - 匿名 PL/SQL block 与 native SQL 的性能

标签 sql oracle performance plsql locking

我有一个 SQL 语句,当在 PL/SQL block 内执行时,它会提供显着不同的性能。

SQL 非常简单。

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

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

但是当在匿名 PL/SQL block 内执行时,它会永远挂起:

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

最佳答案

But when executed inside Anonymous PL/SQL block, it hangs forever:

我猜测两件事:

  1. 您的表 (Existing_Table) 对您在插入语句中使用的列之一有约束。
  2. 您忘记在执行 SQL 语句和 PL/SQL 匿名 block 之间发出提交。

在 SQL 和 PL/SQL 中执行语句不应有性能差异。它应该在几乎相同的时间内执行。 但由于约束或提交,它被阻止,因为该行被锁定。

这是一个例子。

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

create table Existing_Table 
(
  existing_column number primary key
);

create table Existing_Table_2
(
  existing_column number
);    

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

insert into Existing_Table (existing_column) values (1);

结果:

1 row inserted.

在另一个( session 2)上,执行以下 PL/SQL 匿名 block :

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

这将挂起,直到您在 session 1 中发出提交为止。

这是因为 session 1 已“保留”existing_column 的值“1”,并将在您发出提交时“保存”。 session 2 只是等待 session 1 提交或回滚插入。

现在,当我返回 session 1 并发出提交时,该行将被解锁。 但是, session 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.

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

在 session 3 中运行以下 SQL(无需提交):

insert into Existing_Table_2 (existing_column) values (1);

结果:

1 row inserted.

在 session 4 中的匿名 PL/SQL block 内运行相同的 SQL:

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

结果:

PL/SQL procedure successfully completed.

即使在 session 1 中没有提交,它也能很好地插入,因为没有违反任何约束。

请注意,在您发出提交之前, session 3 和 4 中的任何数据都不会真正保存在数据库中。

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

Tracking Oracle blocking sessions

Find blocking sessions

关于sql - 匿名 PL/SQL block 与 native SQL 的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41834555/

相关文章:

c# - 用 C# 编写 SQLServer 用户定义函数

java - JPA 在一个项目中插入触发器之前执行,并在另一个项目中具有不同的行为

java - 在 java 中使用带别名的查询

oracle - 如何正确使用Fluent NHibernate在Oracle中获取下一个Sequence?

r - 在 R 中执行多个逻辑比较的最快方法是什么?

c# - 使用 Active Directory 密码从 C# 连接到 Sql Azure Db 时遇到问题

mysql - 在可空字段上定义的 MySql 唯一约束到底是如何工作的?

mysql - MariaDB 列存储 : Filtering SubQuery by Computed Value

c++ - 侵入式数据结构中的成员钩子(Hook)与基本钩子(Hook)

javascript - 事件事件上的 HTML 元素