Java 不重用PreparedStatements时的性能影响?

Java 不重用PreparedStatements时的性能影响?,java,performance,jdbc,Java,Performance,Jdbc,常见的咒语是总是喜欢PreparedStatement而不是Statement,因为它可以防止SQL注入和(显著)提高性能 但是,如果我的代码一次又一次地重建相同的PreparedStatement,而不是正确地重用它,该怎么办 使用语句的一些性能优势是否仍然存在,或者我是否还剩下一个用于字符串参数的重量级引号转义引擎?重建PreparedStatement仍然比重建语句有优势,但这取决于供应商。例如,在Oracle中,为了不破坏服务器的sql缓存,使用绑定变量是一种很好的做法 Oracle服务

常见的咒语是总是喜欢
PreparedStatement
而不是
Statement
,因为它可以防止SQL注入和(显著)提高性能

但是,如果我的代码一次又一次地重建相同的
PreparedStatement
,而不是正确地重用它,该怎么办


使用
语句的一些性能优势是否仍然存在,或者我是否还剩下一个用于字符串参数的重量级引号转义引擎?

重建PreparedStatement仍然比重建语句有优势,但这取决于供应商。例如,在Oracle中,为了不破坏服务器的sql缓存,使用绑定变量是一种很好的做法

Oracle服务器将对sql字符串进行散列,以查看它是否已经存在于Oracle服务器的sql缓存中。如果是这样,则可以重新使用该语句的缓存pcode。在这种情况下,已经完成了很多工作,如解析、验证、检查授权等,只需要更新参数区域。此外,sql缓存的使用将被最小化,因为不需要在其中放入新语句

在设计糟糕的应用程序中,我们会看到sql缓存中充满了如下语句:

SELECT wage FROM employee WHERE employee_id = 1
SELECT wage FROM employee WHERE employee_id = 2
SELECT wage FROM employee WHERE employee_id = 3
SELECT wage FROM employee WHERE employee_id = 4
从客户端接收的语句不会导致sql缓存中的缓存命中,因此需要再次执行所有解析工作,并将新语句添加到缓存中。不仅解析语句需要额外的工作,而且缓存也变得无用,因为它被这些东西淹没了。在设计良好的应用程序中,您可能能够调整sql缓存的大小,使应用程序运行的每一条语句在预热后都位于缓存中

我们将查询字典表,计算具有类似前缀的语句以查找这些违规者,获取使用绑定参数的应用程序代码(如果是Java代码,则要求开发人员使用PreparedStatements)。然后我们会在缓存中看到这样的语句:

SELECT wage FROM employee WHERE employee_id = :1

一句话。如果客户机在缓存命中率相同的情况下一遍又一遍地将其重新生成为一条准备好的语句,这并不重要。

我很困惑为什么Oracle不从查询中过滤文本以增加“简单”查询的缓存命中率。有人能解释为什么这不会产生与参数化查询相同的缓存结果吗?新版本可能会。我的经验是从Oracle 7到Oracle 11。在以后的版本中,有一个名为
CURSOR\u SHARING
的服务器配置选项,它的作用类似于过滤文本,但它不是默认的,并具有其他效果。我们仍然检查了缓存,并向应用程序开发人员反馈了未作为准备声明的声明。