在预准备语句查询中参数化常量的性能后果



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

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

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

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

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

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

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

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

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

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

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

最新更新