Java 为什么JDBC驱动程序将准备好的语句保存在连接级别?

Java 为什么JDBC驱动程序将准备好的语句保存在连接级别?,java,mysql,postgresql,jdbc,prepared-statement,Java,Mysql,Postgresql,Jdbc,Prepared Statement,我不是想问他们到底做了什么,而是问他们为什么要这样实施。如果准备好的语句完全由数据库处理,那么它不是对所有连接都可用吗?但似乎大部分都是由司机针对连接进行处理,我无法理解其背后的原因 关于Postgres的询问。如果准备了一条语句,它将被发送到数据库,数据库将解析和分析该语句,并发回某种句柄(=id),以后可以根据需要经常使用该句柄来执行该语句。因此,不是将整个语句一次又一次地发送到数据库,而是将句柄和可能的查询参数传递到数据库 正如您已经发现的,准备好的语句绑定到当前数据库连接,因此当连接关闭

我不是想问他们到底做了什么,而是问他们为什么要这样实施。如果准备好的语句完全由数据库处理,那么它不是对所有连接都可用吗?但似乎大部分都是由司机针对连接进行处理,我无法理解其背后的原因


关于Postgres的询问。

如果准备了一条语句,它将被发送到数据库,数据库将解析和分析该语句,并发回某种句柄(=id),以后可以根据需要经常使用该句柄来执行该语句。因此,不是将整个语句一次又一次地发送到数据库,而是将句柄和可能的查询参数传递到数据库

正如您已经发现的,准备好的语句绑定到当前数据库连接,因此当连接关闭时,该语句将从数据库缓存中删除


我不知道你认为向所有关系人公开这些事先准备好的声明会有什么好处。如果您真的希望在服务器上存储公共语句,请使用或

准备好的语句绑定到连接有几个原因(从数据库的JDBC的角度来看),它们归结为“简单”:

  • 资源管理:通过将语句与连接相关联,可以很容易地清理任何尚未显式关闭的语句:如果连接关闭,则任何打开的语句也将关闭

  • 在大多数数据库系统中,语句句柄也是游标句柄,这意味着它一次只能由一个连接使用,将它绑定到一个连接会更有意义

  • 语句生存期(或至少是执行生存期,请参见2)与事务关联,事务也绑定到连接。有些数据库允许一个连接上有多个活动事务,但JDBC假定每个连接有一个活动事务

  • 在大多数数据库系统中,语句的准备取决于准备语句的事务的元数据(DDL)可见性,拥有全局池会使这一点变得复杂(例如允许哪个连接使用/查看哪个语句)

  • 用户权限和特权有时会在准备时进行部分检查。一个全局池将使这一点复杂化(见4)

  • 我现在可能忘记了其他一些原因。我认为最重要的是第一个(如果有一个全球池,其他的将以不同的方式实施)


    这不会阻止数据库系统也拥有一个全局的准备语句池(或者至少是:准备元数据,如访问路径、执行计划等)。然而,从用户的角度来看,一个预先准备好的语句的实例仍然绑定到一个连接。

    哦,我不知道它的返回句柄部分。我在想,如果它发送一些散列/完整的sql查询,那么不管它来自哪个连接,都可以跳过查询编译/规划部分。想法?好吧,这就是你的想法。在另一个连接之前已经发送了相同语句的情况下,对优化进行某种缓存。我不知道数据库(比如Postgres)是否已经(在内部)做到了这一点,但用准备好的语句是无法控制的。不同的故事。据我所知,一些jdbc连接池可以对准备好的语句进行高级处理。从池中获得的连接与原始jdbc连接没有直接关系。他们可以将已经准备好的语句定向到缓存的连接等。次要的一点是:postgres从不发回某种句柄。客户端发送
    PREPARE-name语句作为对协议级别的语句
    或等效语句的查询,PostgreSQL会成功或错误地进行回复。客户端负责提供连接中唯一的名称。