【问题标题】:The Performance Consequences of Parameterizing Constants in PreparedStatement Queries在 PreparedStatement 查询中参数化常量的性能后果
【发布时间】:2018-01-15 11:37:21
【问题描述】:

当使用 JDBC 的 PreparedStatements 查询 Oracle 时,请考虑:

String qry1 = "SELECT col1 FROM table1 WHERE rownum=? AND col2=?";

String qry2 = "SELECT col1 FROM table1 WHERE rownum=1 AND col2=?";

String qry3 = "SELECT col1 FROM table1 WHERE rownum=1 AND col2=" + someVariable ;

逻辑规定rownum 的值始终是一个常数(本例中为1)。而col2 的值是一个不断变化的变量

问题 1: 与使用 rownum 常量的 qry2 相比,使用 qry1(其中 rownum 值是参数化的)是否有任何 Oracle 服务器性能优势(查询编译、缓存等)值是硬编码的?

问题 2: 忽略非性能方面的考虑(如 SQL 注入、可读性等),Oracle 服务器是否有任何性能优势(查询编译、缓存、等)使用 qry2 而不是 qry3(其中 col2 的值被显式附加,未参数化)。

【问题讨论】:

    标签: java oracle jdbc prepared-statement spring-jdbc


    【解决方案1】:

    答案 1: 与 qry2(具有合理绑定变量的查询)相比,使用 qry1(软编码查询)没有性能优势。

    绑定变量通过减少查询解析来提高性能;如果绑定变量是常量,则无需避免额外的解析。

    (可能有一些奇怪的例子,其中添加额外的绑定变量可以提高特定查询的性能。就像任何预测程序一样,有时如果您向 Oracle 优化器提供错误信息,结果会更好。但理解这一点很重要那些是例外情况。)

    答案 2: 与 qry3(硬编码查询)相比,使用 qry2(具有合理绑定变量的查询)有许多性能优势。

    绑定变量允许 Oracle 重用查询解析(查询编译)中的大量工作。例如,对于每个查询,Oracle 需要检查用户是否有权查看相关表。使用绑定变量只需对所有查询执行执行一次。

    绑定变量还允许 Oracle 使用一些仅在第 N 次运行后才会出现的额外优化技巧。例如,Oracle 可以使用基数反馈来改进查询的第二次执行。当 Oracle 在计划中出错时,例如,如果它估计一个连接将产生 1 行,而实际上它产生 100 万行,它有时可以记录该错误并使用该信息来改进下一次运行。没有绑定变量,下一次运行会有所不同,并且无法修复 错误。

    绑定变量还允许许多不同的计划管理功能。有时 DBA 需要在不更改查询文本的情况下更改执行计划。如果查询文本不断变化,SQL 计划基线、配置文件、大纲和 DBMS_ADVANCED_REWRITE 等功能将不起作用。

    另一方面,在一些合理的情况下,最好对查询进行硬编码。有时,像分区修剪这样的 Oracle 特性无法理解表达式,它有助于对值进行硬编码。对于大型数据仓库查询,如果查询要运行很长时间,那么解析查询的额外时间可能是值得的。

    (缓存不太可能影响这两种情况。语句的结果缓存很少见,Oracle 更有可能只缓存语句中使用的表的块。缓冲区缓存可能不关心这些块是否存在一条语句多次访问或多次语句一次访问)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-11
      • 2023-03-24
      • 2017-09-29
      • 2023-04-09
      • 2021-11-12
      相关资源
      最近更新 更多