I/O can show up as significant in
profiling even if I/O is not itself the bottleneck.
It is worthwhile to have separate measurements available for the JDBC
subsystems.
Use JDBC wrappers to measure the performance of database calls.
ResultSet.next( ) can spend a significant amount
of time fetching rows from the database.
JDBC wrappers are simple, robust, and low-maintenance.
Get the JDBC driver right. Using the wrong driver can destroy JDBC
performance.
Use JDBC 3.0 or the latest JDBC version if possible.
Use connection pooling.
Optimize the SQL to apply set-based
(multi-row) processing rather than one row at a time. Use temporary
tables and conditional expressions for extra efficiency. Avoid
expensive expressions like upper( ). Use extra
fields, like a COUNT field.
Avoid moving, deleting, and adding rows where possible: use
preinserted and null value rows. Avoid joins, use indexes.
Use the EXPLAIN statement to examine the SQL operation.
Don't use SELECT * ..., use
SELECT Field1, Field1, ....
Access fields by index, not by name (i.e.,
resultSet.getString(1) not
resultSet.getString("field1")).
Cache row and field data rather than re-query to access the same
data. Using a wrapper, you can transparently cache rows and tables.
Consider using an in-memory (replicated) database.
Use parameterized PreparedStatements except where
a statement will be executed only a few times and there is no spare
time to initialize a PreparedStatement. Reuse the
connection associated with the PreparedStatement
unless the connection pool supports
PreparedStatement pooling (as JDBC 3.0 does).
Create SQL query strings statically, or as efficiently as possible if
created dynamically.
Tune batched row access using fetch sizing.
Batch updates with executeBatch( ), explicitly
managing the transaction by turning off auto-commit.
Try to closely
match Java data types and database data types. Converting data
between badly matching types is slow.
Avoid using slow metadata calls,
particularly getBestRowIdentifier( ),
getColumns( ), getCrossReference(
), getExportedKeys( ),
getImportedKeys( ), getPrimaryKeys(
), getTables( ), and
getVersionColumns( ).
Use metadata queries to reduce the amount of transfers needed in
subsequent database communications.
Consider using stored procedures to move some
execution to the database server. Don't use a stored
procedure to replace any simple SQL calls. Stored procedures are best
used to avoid moving data back and forth across the network.
Take manual control of transactions
with explicit begin and commit calls, turning off auto-commit mode,
and combining close transactions to minimize the overall transaction
costs.
Use the lowest transaction isolation level that
won't corrupt the application.
Avoid letting the user control when a transaction terminates.
Use optimistic transactions when reads predominate over writes.
Savepoints probably have high overheads.
Small, lightly used databases can be efficiently located on the same
machine as the application server; otherwise, another machine is
probably better.