在我的数据库的多个地方,开发人员使用了动态sql而不是静态sql。他们说这是为了提高性能。有人可以告诉我动态sql是否真的可以提高存储过程或plsql块的性能吗?
哪个执行速度更快,为什么? 1。
begin execute immediate 'delete from X'; end;
2。
begin delete from X; end;
您的示例代码非常简单,几乎没有什么区别,但是在那种情况下,静态版本最有可能执行得更好。
使用动态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
在最终版本中,Oracle将选择通用的解释计划。在第一个版本中,它可能决定最好的计划是从状态索引开始(知道“ U”未处理的条目在总数中只占很小的一部分)。
您可以通过不同的静态语句来实现这一点,但是如果您有更复杂的语句(仅需更改几个字符),则动态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
各个语句将很快,但是整个系统的性能将下降,因为它会杀死共享资源。
另外-使用动态SQL在编译时捕获错误要困难得多。如果使用PL / SQL,则会浪费大量的编译时间检查。即使使用JDBC之类的东西(将所有数据库代码都移到字符串中-很好!),您也可以使用预解析器来验证JDBC内容。动态SQL =仅运行时测试。
开销
立即执行的开销很小-大约是千分之一秒- 但是,如果它在循环内/在每个对象调用一次的方法上等等,它可以加起来。通过替换动态对象,我曾经获得了10倍的速度提高具有生成的静态SQL的SQL。但是,这使代码复杂化,并且仅因为我们需要速度而完成了。