我知道,第一次使用时,jdbc会保留已编译的预准备语句,以便下次以更有效的方式访问它。
现在,假设我有这种情况:
public class MyDao{
public void doQuery(){
try(PreparedStatement stmt = connection.prepareStatement(MY_STMT)){
}
}
}
以下代码段是否会将已编译的预准备语句保留在内存中?
摘录1:
MyDao dao = new MyDao();
dao.doQuery(); //first one, expensive
dao.doQuery(); //second one, less expensive as it has been already compiled
摘录2:
MyDao dao = new MyDao();
dao.doQuery(); //first one, expensive
MyDao dao2 = new MyDao();
dao2.doQuery(); //will it be expensive or less expensive?
我担心,通过创建一个新的dao对象,jvm会将该预处理语句视为一个新语句,因此它不会编译它。
而且,如果情况并非如此,那么jvm是否会忘记"编译后的语句会再次编译吗?
由于
答案 0 :(得分:2)
准备语句重用的最基本方案是您的代码保持PreparedStatement
打开并重用该预准备语句。您的示例代码不符合此条件,因为您关闭了预准备语句。另一方面,由于潜在的并发问题(例如,如果多个线程使用相同的DAO,您可能正在执行来自多个线程的奇怪值组合等),尝试保持为多个方法调用打开预准备语句通常不是一个好的计划。
某些JDBC驱动程序在内部具有(可选的)预准备语句缓存(池)以供重用,但只有在尝试在同一物理连接上再次准备相同的语句文本时才会重复使用。查看驱动程序的文档。
在一个单独的层面上,数据库系统可能会缓存预准备语句的执行计划,如果再次准备相同的语句文本(即使是不同的连接),它也可以(将)重用它。
答案 1 :(得分:0)
你是对的,它会被再次编译。 PreparedStatements只有在您多次实际使用语句本身时才会重复使用(即,您多次调用executeQuery
)。
但是,我不会过分担心编制声明的成本。如果您的查询花费的时间超过几毫秒,则编译的成本将是微不足道的。只有在每秒执行1000次操作时,编译语句的开销才会变得明显。
答案 2 :(得分:0)
做一个基准。这是获得性能差异确定性的最佳方法。不一定是在服务器端始终重新编译语句的情况。根据您的RDBMS,它可以缓存先前编译的语句。为了最大化缓存命中概率,请始终提交完全相同的参数化SQL文本,并通过相同的连接进行。