在我的数据库中的几个地方,开发人员使用动态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.然而,这使代码变得复杂,并且只是因为我们需要速度而完成.