Bertrand Florat Tech articles Others articles Projects Cours et papiers CV Contact

Undocumented Oracle PreparedStatement optimization

We just get a 20% response time gain on a 600+ lines query under Oracle. Our DBA noticed that queries were faster when launched from SQLDeveloper than from our JEE application using the JDBC Oracler 11g driver. We looked at the queries as they actually arrived to the Oracle engine and they where under the form : SELECT... WHERE col1 like ':myvar1' OR col2 LIKE ':myvar2' AND col3 IN (:item1,:myvar2,...) and not 'SELECT... WHERE col1 LIKE ':1' OR col2 LIKE ':2' AND col3 IN (:3,:4,...) like usual when using PreparedStatement the regular way.

Indeed, every PreparedStatement documentation I'm aware of, beginning with the one from Sun states that we have to use '?' to represent bind variables in queries. These '?' are replaced by ':1', ':2', '3' ... by the JDBC driver. So the database has no way to now in our case that :2 and :4 have the same value. This information is lost.

We discovered that we can use PrepareStatement by providing queries with named bind variables instead of '?'. Of course, we still have to set the right value using the setXXX(int position,value) setters for every bind variable occurrence in the query. Then, queries arrive to Oracle like when using SQLDeveloper, with named bind variables.

OK but what's the deal with all this ?

I'm not sure but I think that this optimization may allow Oracle optimizer to be cleverer, especially for queries with redundant parts. It is especially good for queries with duplicated sub SELECT with IN condition containing all the same list of items. Maybe Oracle create on-the fly WITH clauses or similar optimizations in this case ?

Note that this optimization may only work with Oracle and is probably only useful for very large or redundant queries. I don't recommend it in most cases. AFAIK, neither Hibernate nor Spring-JDBC implements this optimization.