MySQL JDBC驱动程序将这两个属性定义为:
useServerPrepStmts-如果服务器支持的话,使用服务器端准备好的语句? cachePrepStmts- 驱动程序是否应该缓存客户端准备好的语句的PreparedStatements的解析阶段,是否适合服务器端准备好的语句和服务器端准备好的语句本身的“检查”?
useServerPrepStmts-如果服务器支持的话,使用服务器端准备好的语句?
cachePrepStmts- 驱动程序是否应该缓存客户端准备好的语句的PreparedStatements的解析阶段,是否适合服务器端准备好的语句和服务器端准备好的语句本身的“检查”?
客户端准备好的语句是否可以重用PreparedStatements对象?
PreparedStatements
如果useServerPrepStmts启用,则由于MySQL没有执行计划缓存,因此确切地缓存了什么?
useServerPrepStmts
首先,区分客户端和服务器准备好的语句很重要。
客户准备的语句是“模拟”准备的语句。这意味着在客户端将SQL语句字符串标记为令牌,并且在将语句发送到服务器执行之前,所有占位符都将被文字值替换。每次执行时,完整的SQL语句都会发送到服务器。您可以使用常规日志来调查其工作原理。例如
以下代码:
ps=conn.prepareStatement("select ?") ps.setInt(1, 42) ps.executeQuery() ps.setInt(1, 43) ps.executeQuery()
将显示在日志中:
255 Query select 42 255 Query select 43
“查询”表示,在协议级别上,将COM_QUERY发送命令,并在其后添加语句字符串。
COM_QUERY
服务器准备语句是“ true”准备语句,表示将查询文本发送到服务器,进行解析,然后将占位符和结果信息返回给客户端。这是设置时得到的useServerPrepStmts=true。语句字符串仅一次通过COM_STMT_PREPARE调用发送到服务器(在此处记录)。每次执行都是通过发送COM_STMT_EXECUTE带有准备好的语句句柄和文字值来代替占位符来执行的。
useServerPrepStmts=true
COM_STMT_PREPARE
COM_STMT_EXECUTE
与客户准备好的示例形成对比,我们可以使用类似的代码块(但是这次启用了服务器准备的语句):
ps2=conn2.prepareStatement("select ?") ps2.setInt(1, 42) ps2.executeQuery() ps2.setInt(1, 43) ps2.executeQuery()
日志将显示:
254 Prepare select ? 254 Execute select 42 254 Execute select 43
您可以看到该语句在执行前已准备好。该日志为我们提供了帮助,并显示了执行的完整语句,但实际上,每次执行时,仅占位符值从客户端发送到服务器。
许多连接池将在连接的使用之间缓存准备好的语句,这意味着,如果您调用conn.prepareStatement("select ?"),它将PreparedStatement在后续调用中使用相同的语句字符串返回相同的实例。当将连接返回到事务之间的池中时,这有助于避免在服务器上重复准备相同的字符串。
conn.prepareStatement("select ?")
PreparedStatement
MySQL JDBC选项cachePrepStmts将以这种方式缓存准备好的语句(客户端和服务器准备好的语句),以及缓存语句的“可准备性”。MySQL中有一些语句无法在服务器端准备。如果驱动程序认为可能,则驱动程序将尝试在服务器上准备一条语句,如果准备失败,则退回给客户端准备的语句。由于需要往返服务器,因此该检查很昂贵。该选项还将缓存此检查的结果。
cachePrepStmts
希望这可以帮助。