在Oracle中将绑定变量与文字混合使用

时间:2011-12-20 16:15:33

标签: sql oracle bind-variables

这个问题可能更适合DB stackexchange站点,但我不确定。

无论如何,我正在处理优化查询,并且我了解到使用绑定变量会使解析器无法正常工作。我们已经看到正在运行的查询有所改进,但我想知道是否将我们的软件传入的静态变量用于绑定变量也是有帮助的。这是一个例子:

select *
from report
where report.name = :1
and report.enabled = '1'

我可以说出来

select *
from report
where report.name = :1
and report.enabled = :2

我只是做出改变,但是在软件中实际执行它并看到它所带来的差异的过程有点漫长而乏味。有没有人知道混合文字(如第一个例子中)是否会损害优化器效率,即使它们始终相同?

提前致谢。

4 个答案:

答案 0 :(得分:7)

我不确定I learned that using bind variables makes the parser not work as hard你的意思,但我猜......


您是在客户端构建SQL字符串并将它们发送到oracle数据库来执行吗?

如果是这样,参数化查询的行为意味着数据库引擎可以看到使用相同的执行计划/解释计划可以满足多个查询(尽管具有不同的参数)。

这意味着引擎不需要重新编译本机SQL,并且可以在缓存中重新使用计划(可能)。

如果没有参数化,并且“name”的值不同,引擎会将查询视为完全不同,而不会注意到相似性。这将导致SQL被编译,除非 exact 相同的字符串已经在缓存中。


但是,如果您的查询始终具有report.enabled = 1,则无需对查询的该部分进行参数化。由于它是静态的,不使用参数的行为不会使它看起来像一个不同的查询,也不会导致它被重新编译。

相反,您实际上可以根据索引,数据统计等进行节省。例如,如果99%的数据“启用= 1”,则可能会获得与1%不同的计划你的数据被“启用= 1”。但是引擎只会在已知的查询中针对“enabled = 1”进行优化,所查找的值始终 1.而且只有当它是静态指定(作为文字)。


简而言之,如果它确实是静态值,请不要对其进行参数化。

答案 1 :(得分:4)

如果您的SQL确实包含常量(即该子句总是enabled=1),我会看到在SQL中将它们作为文字的几个原因:

  • 当您遇到性能问题而不能立即访问绑定值时(例如某些跟踪文件中),调试会更容易。
  • 优化器有时可以在使用常量时更有效地估计查询的基数(即:禁用绑定查看时或DBMS的旧版本),特别是如果您在此列上有直方图的统计信息
  • 您需要将常量用于某些特定的计划选项(例如,分区修剪)

此外,除了性能之外,使用参数化查询的另一个主要原因是防止SQL注入。真常量不会受SQL注入,因为它们将由您的代码提供,而不是由外部源提供。

答案 2 :(得分:0)

答案常常是“取决于”。

什么?您的应用程序是OLTP(许多查询,小结果集)还是DSS(少量查询,大量数据)?您正在寻找从绑定到文字的列中涉及的偏差是什么?这些列是否需要可绑定,或者它们是否始终绑定到相同的值?

答案 3 :(得分:0)

当Oracle收到SQL语句时,它首先查看SQL语句及其执行计划是否已存在于缓存中。如果是,则节省了重新创建执行计划的成本,从而节省了执行时间。为了使传入的SQl语句与缓存中的一个匹配,它必须是完全匹配(包括leterals,绑定变量和空格)。这就是为什么鼓励使用绑定变量以使声明对于变量的不同值(以及因此不同的文字)保持相同。但是如果一直使用相同的文字,那么使用bind varialbes没有区别。在解析和执行计划生成方面,两种情况下的性能都是相同的。