PreparedStatement 查询中参数化常量的性能后果

The Performance Consequences of Parameterizing Constants in PreparedStatement Queries

当使用 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: 使用 qry1 where rownum value 是否有任何 Oracle 服务器性能优势(查询编译、缓存等)是参数化的,在 qry2 上,其中 rownum 的常量值是硬编码的?

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

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

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

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

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

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

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

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

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

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