PreparedStatement如何在Java中内部工作:SQL的编译和缓存如何工作
我在互联网上读到过这方面的消息,但我无法回答一些问题
Q1据说在执行PreparedStatement时,DBMS只需运行PreparedStatement SQL语句,而不必首先编译它。我的问题是什么时候准备发言。调用execute()会发生什么?(我的理解是:不带任何参数的sql被发送到DBMS,由DBMS编译和缓存以供将来使用。然后发送参数,DBMS用占位符和执行替换它们。)
Q2如果下次我执行PreparedSteement。使用相同的sql执行(),然后会发生什么?(我的理解是:DBMS将sql与以前的sql进行比较,如果匹配,则采用已编译的sql、替换参数和执行。)
Q3如果我偶尔调用数据库,那么prepared语句将无助于提高性能,因为在此期间数据库缓存将被清除。因此每次都会编译sql。对吧?
# 1 楼答案
java.sql.PreparedStatement
是JRE定义的APIexecute()
的实际内部行为取决于DBMS供应商提供的JDBC驱动程序实现例如,有一些嵌入式数据库(SQLite,H2),其中
sending statement to server
毫无意义您应该查阅您正在使用的JDBC驱动程序的文档
# 2 楼答案
除了rkosegi上面的回答之外,我还想进一步描述一下如何使用PostgreSQL驱动程序,因为它突出了这里的一些困难
使用PostgreSQL驱动程序(请参见documentation),行为实际上是可配置的,并且相当复杂
PostgreSQL查询协议允许单独发送查询和参数,因此PreparedStatement API不需要执行请求数据库准备语句然后稍后执行的过程。折衷的办法是,在初始准备过程中,服务器端准备会带来额外的开销,以及何时重新使用查询计划的问题,但这与较短的查询重新使用启动时间相抵消。因此,如果您正在进行优化,并且重复查找要准备的单个记录,而您正在可变范围上运行或不重复使用语句,那么您可能不会这样做。这是在数据库连接上配置的。这通常设置为一个阈值,用于确定在一定量的重复使用之后何时开始缓存计划
当不使用服务器端prepare时,驱动程序将在同一命令中分别向数据库发送参数化查询和参数。然后,服务器解析查询,将变量插入适当的位置,并规划。计划运行后将被丢弃
然后使用服务器端prepare,但是它可以按照您所描述的那样工作
所以这里有一个很难的例子,说明为什么你不能问这个问题并得到一个明确的答案。JDBC提供了一个编程接口,驱动程序提供了详细的工作原理。prepareStatement未定义是否缓存查询计划。那是由司机决定的
# 3 楼答案
preparedStatement
需要DBMS的支持如果sql已经编译,DB将缓存它。当同一个参数再次出现时,只需发送参数即可完成缓存的sql
prepareStatement
有三个优点:使代码更清晰,以便更容易阅读
尽可能提高性能。重新计算编译时间
最重要的是,它使sql更加安全。如果您的sql如下所示:
有人给它一个userid值,比如
该语句将按如下方式执行sql
如果操作员真的有权这样做,那么对数据库来说这是一个非常危险的操作
如果我们使用
preparestatement
数据库将把sql编译为
"select * from users where userid = '
'
“并等待参数”?“这意味着sql将像这样执行将参数视为字符串。 这是接口
java.sql.Connection
类中的注释。读一下