【问题标题】:Mixing Bind Variables with Literals in Oracle在 Oracle 中将绑定变量与文字混合
【发布时间】:2012-01-24 14:14:58
【问题描述】:

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

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

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

我可以说出来

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

我只想进行更改,但在软件中实际进行更改并查看它所产生的差异的过程有点漫长而乏味。有谁知道混合文字(如第一个示例)是否会损害优化器的效率,即使它们始终相同?

提前致谢。

【问题讨论】:

    标签: sql oracle bind-variables


    【解决方案1】:

    如果您的 SQL 确实包含常量(即子句始终为 enabled=1),我认为有几个原因让它们在您的 SQL 中作为文字:

    • 当您遇到性能问题并且无法立即访问绑定的值(例如在某些跟踪文件中)时,调试起来会更容易
    • 优化器有时可以在使用常量时更有效地估计查询的基数(即:当绑定窥视被禁用或旧版本的 DBMS 时),尤其是当您在此列上有带有直方图的统计信息时
    • 您需要为某些特定计划选项使用常量(例如分区修剪)

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        我不太确定你所说的 I learned that using bind variables makes the parser not work as hard 是什么意思,但我猜……


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

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

        这意味着引擎不需要重新编译原生 SQL,并且可以重用缓存中已经(可能)的计划。

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


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

        相反,您实际上可能会根据索引、数据统计等节省开支。例如,如果您的数据中有 99% 是“启用 = 1”,那么与 1% 相比,您可能会得到不同的计划您的数据被“启用 = 1”。但是引擎只会在查询中针对“启用 = 1”进行优化,其中 已知 正在查找的值是 always 1。只有当它是静态指定(作为文字)。


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

        【讨论】:

          【解决方案4】:

          答案通常是“视情况而定”。

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-07-19
            • 1970-01-01
            • 1970-01-01
            • 2020-03-03
            • 2011-03-18
            • 2012-11-17
            • 2019-01-02
            • 2015-02-07
            相关资源
            最近更新 更多