静态与动态sql

静态与动态sql,sql,oracle,plsql,Sql,Oracle,Plsql,在我的数据库中,有几个地方的开发人员使用了动态sql而不是静态sql。他们说这样做的原因是为了提高性能。有人能告诉我动态sql是否真的能提高存储过程或plsql块的性能吗 哪个执行速度更快?为什么? 1. 二, 不幸的是,这在个案基础上确实有所不同 对于给定的示例,可能没有可测量的差异。但对于更复杂的示例,您可能需要测试自己的代码 在评论中给出的链接@DumbCoder有一些很好的经验法则,这在很大程度上也适用于Oracle。您可以使用类似的方法来帮助您做出决定,但没有“动态比静态快”这样的

在我的数据库中,有几个地方的开发人员使用了动态sql而不是静态sql。他们说这样做的原因是为了提高性能。有人能告诉我动态sql是否真的能提高存储过程或plsql块的性能吗

哪个执行速度更快?为什么?
1.

二,


不幸的是,这在个案基础上确实有所不同

对于给定的示例,可能没有可测量的差异。但对于更复杂的示例,您可能需要测试自己的代码


在评论中给出的链接@DumbCoder有一些很好的经验法则,这在很大程度上也适用于Oracle。您可以使用类似的方法来帮助您做出决定,但没有“动态比静态快”这样的简单规则。您的示例代码非常简单,几乎没有什么不同,但在这种情况下,静态版本的执行效果可能会更好

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

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

例如,如果您有一个类似于状态字段的字段,其中的数据分布不均匀(而是索引)

当95%的数据被“p”处理时,请考虑以下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语句的每次重复都会导致软解析,这与静态语句相比是一个小开销,但仍然是一个开销

每个新的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=仅限运行时测试

管理费用


execute immediate的开销很小——只有千分之一秒——但是,如果它在循环内/在一个名为“每个对象一次”的方法上/等等,那么它就可以加起来。我曾经通过用生成的静态SQL替换动态SQL,使速度提高了10倍。但是,这使代码变得复杂,之所以这样做是因为我们需要速度。

我不确定像“从X删除”这样的查询,但一般来说,如果您的查询有参数,动态查询可以工作得更快,我多次看到它。为什么?在编译存储过程数据库时,似乎不知道参数可能是什么,并且可能选择了错误的计划。在动态查询的情况下,当我用查询创建字符串并执行它时,所有参数都被插入,执行计划更好。这听起来很奇怪,但当性能重要时,我也会这样做。回到您的问题->您的查询是像您编写的那样,还是更复杂(使用存储过程插入的参数)?大多数查询都很简单,可以以静态方式编写。这就是为什么我想知道,当动态查询可以以静态方式编写时,为什么要使用它。我认为你的论点是正确的——如果它可以以静态方式编写,那么最好是以静态方式编写。经验法则(可能涉及失去上述拇指):OLTP应用程序和处理应该绑定/参数化SQL;DSS(决策支持)/DW系统应该是动态/文字SQL。JulesLt在他的回答中有很好的观点,并在讨论开销时暗示了一些需要明确说明的内容——将绑定变量考虑、解析等放在一边。,PL/SQL块中的executeimmediate总是比等效的PL/SQL调用有缺点,因为执行将涉及到到到SQL引擎的上下文切换。
   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
SELECT col FROM table WHERE id = 5
SELECT col FROM table WHERE id = 20
SELECT col FROM table WHERE id = 7