在Oracle JDBC驱动程序中,有一个用于缓存预准备语句的选项。我对此的理解是,准备好的语句由驱动程序预编译,然后进行缓存,从而提高缓存预准备语句的性能。
我的问题是,这是否意味着数据库永远不必编译那些准备好的语句? JDBC驱动程序是否发送了一些预编译表示,或者数据库本身是否还存在某种解析/编译?
答案 0 :(得分:4)
当您使用隐式语句缓存(或显式语句缓存的Oracle扩展)时,Oracle驱动程序将在(!)close()之后缓存预备或可调用语句,以便与物理连接重用。
所以会发生什么:如果使用了准备好的Statement,并且物理连接从未见过它,它会将SQL发送到DB。根据DB之前是否已经看过该语句,它将进行硬解析或软解析。所以通常如果你有一个10连接池,你会看到10个解析,其中一个解析很难。
在连接上关闭语句后,Oracle驱动程序会将解析语句(共享游标)的句柄放入LRU缓存中。下次在该连接上使用prepareStatement时,它会找到要使用的缓存句柄,而根本不需要发送SQL。这导致执行NO PARSE。
如果在物理连接上使用了更多(不同)预准备语句,而缓存大小不足,则关闭最长的未使用的开放共享游标。这会在下次再次使用该语句时导致另一个软解析 - 因为SQL需要再次发送到服务器。
这基本上与中间件的一些数据源更通用地实现的功能相同(例如JBoss中的prepared-statement-cache)。只使用其中一个来避免双重缓存。
您可以在此处找到详细信息:
http://docs.oracle.com/cd/E11882_01/java.112/e16548/stmtcach.htm#g1079466
另请查看支持此功能并与FAN交互的Oracle Unified Connection Pool(UCP)。
答案 1 :(得分:3)
我认为这回答了你的问题:(对不起,它是powerpoint,但它定义了如何将准备好的语句发送到Oracle,Oracle如何将其存储在共享SQL池中,处理它等)。从Prepared语句中获得的主要性能提升是,在第1 + n次运行中,您将避免对sql语句进行硬解析。
Oracle(或者选择的数据库)将存储准备好的语句,java只是发送它与db将选择的相同语句(这是有限的资源,但是在没有查询的x时间之后,共享的sql将被清除esp。非常见的查询)然后需要重新解析 - 无论它是否缓存在你的java应用程序中。