静态vs动态sql

Pra*_*tav 5 sql oracle plsql

在我的数据库中的几个地方,开发人员使用动态sql而不是静态.他们说这是为了提高绩效.有人能告诉我,如果动态sql能真正提高存储过程或plsql块的性能吗?

哪个会执行得更快,为什么?
1.

begin  
    execute immediate 'delete from X';  
end;
Run Code Online (Sandbox Code Playgroud)

2.

begin  
    delete from X;  
end;
Run Code Online (Sandbox Code Playgroud)

Jul*_*sLt 13

您的示例代码非常简单,几乎没有什么区别,但在这种情况下,静态版本很可能会更好地执行.

使用动态SQL提高性能的主要原因是SQL语句可能会有很大的不同 - 即您可以在运行时根据系统状态向WHERE子句添加额外的代码(通过子查询进行限制)在地址,如果输入地址,等).

另一个原因是有时使用Bind变量作为参数可能会适得其反.

例如,如果您有类似状态字段的内容,其中数据分布不均匀(但已编入索引).

当95%的数据被'处理'时,请考虑以下3个陈述

   SELECT col FROM table 
   WHERE status = 'U'-- unprocessed
   AND company = :company

   SELECT col FROM table 
   WHERE status = 'P' -- processed
   AND company = :company

   SELECT col FROM table
   WHERE status = :status
   AND company = :company
Run Code Online (Sandbox Code Playgroud)

在最终版本中,Oracle将选择通用的解释计划.在第一个版本中,它可能决定最佳计划是从状态索引开始(知道'未处理的条目只占总数的一小部分).

您可以通过不同的静态语句实现它,但是如果您有更复杂的语句,只有几个字符更改,动态SQL可能是更好的选择.

缺点

同一个动态SQL语句的每次重复都会产生一个软解析,与静态语句相比,这是一个很小的开销,但仍然是开销.

每个NEW sql语句(动态或静态)也会导致对SGA(共享内存)的锁定,并可能导致推送"旧"语句.

一个糟糕但常见的系统设计是让某人使用动态SQL生成只能按键变化的简单选择 - 即

SELECT col FROM table WHERE id = 5
SELECT col FROM table WHERE id = 20
SELECT col FROM table WHERE id = 7
Run Code Online (Sandbox Code Playgroud)

单个语句会很快,但整体系统性能会恶化,因为它会破坏共享资源.

此外 - 使用动态SQL在编译时捕获错误要困难得多.如果使用PL/SQL,则会丢弃良好的编译时间检查.即使使用类似JDBC的东西(将所有数据库代码移动到字符串中 - 好主意!),您也可以获得预解析器来验证JDBC内容.动态SQL =仅限运行时测试.

管理费用

执行立即数的开销很小 - 它是千分之一秒 - 然而,如果这是在一个循环/在每个对象/一次调用一次的方法内,它可以加起来.我曾经通过替换动态获得了10倍的速度提升SQL生成的静态SQL.然而,这使代码变得复杂,并且只是因为我们需要速度而完成.