我正在查看一个非常慢的SQL查询(源自使用JBoss 5.1中部署的Hibernate的Java应用程序)。这个特定的查询返回了大约1万条记录,但仍然花费了40多秒或更长时间。

我最终嗅出了数据库的流量(wireshark有一个用于TNS的解剖器),并且发现了意外情况。当数据来自服务器时,每个结果行都位于其自己的TNS数据包中。此外,在从数据库发送下一个TNS数据包之前,客户端(即,应用服务器)已确认每个TNS数据包。对于10K记录,需要进行10K次往返来获取数据包并进行确认。对性能的影响是巨大的。

这是非常低效的。 TCP允许更大的数据包,并具有多种机制(滑动窗口,延迟的ACK)以减少延迟并提高吞吐量。但是,在这种情况下,最上面的TNS协议增加了自己的协商。

如果我从Oracle的SQL Developer运行相同的查询,则看不到此模式。查询将在大约1/10的时间内完成,而无需进行数千次往返。

简短版:Oracle的有线协议(TNS)似乎在每个查询结果行的一个TNS数据包中传递数据,并要求客户端在服务器发送下一个数据包之前先确认每个数据包。

我已经找到了关于此[此处] [1]的一些信息(向下滚动到“ tnsnames.ora文件中的SDU和TDU参数”部分)。

因此,我的问题是:是否可以控制Oracle驱动程序的行为(我使用的是10.2.0.4.0),以便TNS协议更有效?同样,这是在JBoss中部署的非常标准的J2EE应用程序。

非常感谢!

最佳答案

调整tnsnames.ora和listener.ora中的SDUTDU参数

将当前语句的批次大小设置为100。

  ((OracleStatement)stmt).setRowPrefetch (100);


注意:


设置预取大小可能会影响
应用程序的性能。
增加预取大小将
减少往返次数
需要获取所有数据,但会
增加内存使用率。这将
取决于数量和大小
查询中的列数和
预期将返回的行。它会
也取决于内存和CPU
JDBC客户端计算机的加载。
独立客户端的最佳选择
应用程序将不同于
重载的应用程序服务器。的
网络的速度和延迟
连接也应考虑连接也应考虑


(来自Oracle Database JDBC Developer's Guide and Reference

可用的连接属性here

也可以看看Oracle UCP

09-16 04:58