I was looking at a very slow SQL query (originating from a Java app using Hibernate deployed in JBoss 5.1). This particular query returned about 10K records but still took 40s or more.
I ended up sniffing the traffic with the database (wireshark has a dissector for TNS) and found something unexpected. When data was coming from the server, each result row was in its own TNS packet. Furthermore, each TNS packet was acknowledged by the client (i.e. the app server) before the next one was sent from the database. For 10K records, there are 10K roundtrips to get a packet and acknowledge it. The impact on the performance is huge.
This is terribly inefficient. TCP allows larger packets and has a number of mechanisms (sliding windows, delayed ACKs) to reduce latency and increase throughput. However, in this case it's the TNS protocol on top that adds its own negotiation.
If I run the same query from the Oracle's SQL Developer, I don't see this pattern. The query completes in about 1/10 of the time, without thousands of round trips.
Short version: Oracle's wire protocol (TNS) seems to pass data in one TNS packet per query result row and requires each packet to be acknowledged by the client before the server sends the next one.
I've found some info about this [here][1] (scroll down until the section on 'The SDU and TDU parameters in the tnsnames.ora file').
And thus my question: is it possible to control the behaviour of the Oracle driver (I'm using 10.2.0.4.0) so the TNS protocol is more efficient? Again, this is a pretty standard J2EE app deployed in JBoss.
Thanks a lot!