Sql 预编译方面的语句与准备好的语句

Sql 预编译方面的语句与准备好的语句,sql,jdbc,Sql,Jdbc,我理解使用语句和PreparedStatement之间的主要区别(PreparedStatements允许传入参数)。但我读到了这两者之间的细微差别——即PreparedStatement比泛型语句更快,因为PreparedStatement SQL是预编译的 预编译到底意味着什么?为什么它会带来不同 准备好的语句执行以下检查: 确保表和列存在 确保参数类型与其列匹配 解析SQL以确保语法正确 编译并缓存已编译的SQL,以便无需重复这些步骤即可重新执行 编译过程中最重要的部分是创建查询计划 顾

我理解使用语句和PreparedStatement之间的主要区别(PreparedStatements允许传入参数)。但我读到了这两者之间的细微差别——即PreparedStatement比泛型语句更快,因为PreparedStatement SQL是预编译的


预编译到底意味着什么?为什么它会带来不同

准备好的语句执行以下检查:

  • 确保表和列存在
  • 确保参数类型与其列匹配
  • 解析SQL以确保语法正确
  • 编译并缓存已编译的SQL,以便无需重复这些步骤即可重新执行

编译过程中最重要的部分是创建查询计划

顾名思义,查询计划指示数据库应如何执行查询(例如,要使用哪些索引,要使用的连接类型,如嵌套循环/哈希/合并连接等)。 这可能需要时间,因为数据库需要分析表上的信息,以便很好地猜测什么是最佳的(例如,表大小、可用索引、索引的具体程度等)

虽然准备好的语句可以节省时间,但您必须小心,因为它们有时会使您的程序变慢。为什么?因为在编译过程中不提供where子句值,所以数据库必须猜测您将要提供的值,并且它可能会选择导致次优查询计划的值

这对于范围查询可能最为明显。例如,假设您创建了一个准备好的语句,其中最小日期和最大日期作为参数。此查询将用于检索几天的事务。考虑到较小的日期范围,如果数据库使用日期非聚集索引,则执行此查询可能是最有效的

但是,由于数据库不知道您将提供哪些参数,因此数据库可能会针对更大的日期范围(例如一年或更长)进行优化,这可能是使用表扫描执行的最有效方法。在这种情况下,使用prepared语句会减慢程序的速度(除非您向数据库提供关于要优化哪些参数的提示,或者明确指示要使用哪些索引)

当然,如果在您准备好的语句中,您将提供的参数将指向单个记录(例如表上的唯一键),那么数据库在创建查询计划时确实不会出错


我想我是想强调这里有正反两面。PreparedStatements在某些情况下可以更快,但您必须小心。

检查表和列的存在性、验证语法、验证访问权限、准备执行计划:db服务器对每个语句都执行此操作,无论是否准备好。像Oracle这样的服务器还根据接收到的语句字符串的散列来缓存语句(准备好或不准备好)。一旦这项工作完成,并且db服务器已经“准备好”了一个内存区域,那么jdbc驱动程序就可以绑定参数并使用这个服务器对象。然后重新绑定新参数并再次使用,而无需重新准备语句。如果驱动程序是这样实现的。关于预编译的详细信息:[[1]: