2017-08-08 75 views
1

当使用JDBC的预处理语句查询甲骨文,考虑一下:参数化常量在PreparedStatement的查询的性能后果

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:是否有任何Oracle服务器的性能优势(编译查询,缓存等)使用qry1其中ROWNUM值参数,在qry2这里的rownum的恒定值是硬编码?

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

回答

3

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

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

(可能有一些奇怪的例子,添加额外的绑定变量可以提高某个特定查询的性能,就像任何预测程序一样,偶尔如果您向Oracle优化器提供不良信息,结果会更好。明白这些都是特殊情况下)

答2:有很多性能上的优势,使用qry2(以合理的绑定变量查询)在qry3(硬编码的查询)。

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

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

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

另一方面,有一些合理的情况下最好对查询进行硬编码。有时,像分区修剪这样的Oracle功能无法理解表达式,并且它有助于对值进行硬编码。对于大型数据仓库查询,如果查询要运行很长一段时间,解析查询的额外时间可能是值得的。 (高速缓存不太可能影响任何一种情况,一个语句的结果高速缓存很少,Oracle很可能只高速缓存语句中使用的表的块,缓冲区高速缓存可能并不关心这些块多次访问或多次访问一次)