I am facing a problem in my company that is - our program's speed is not fast enough. To be more specific, we are telecommunication company and this program handle call/internet serfing transaction made by every mobile phone users in our city. Because the amount of download content made by the iphone users is just too much, our program cannot handle them fast enough.
The situation is, the amount of transaction made by users are double of the transaction processed by our program. Most of the running time of the program are dominated by DB transactions.
I've search through the internet and browsed some sites ( for example: http://www.javaperformancetuning.com/tips/rawtips.shtml ) talking about Java performace in DB, but I cannot find a suggestion suitable for us.
These advices are not applicable/already used, for instance:
1. Use prepared statements. Use parameterized SQL
Already used prepared statement. Each time will use different parameter by clear parameters and set parameters.
2. Tune the SQL to minimize the data returned (e.g. not 'SELECT *').
Sure, already used.
3. Use connection pooling.
We hold a single connection during the program's execution. And I doubt that pooling cannot solve the problem because our program act as 1 user, so there are no problem for concurrent access to DB. If anyone of you think pooling is good, please tell me why. Thanks.
4. Try to combine queries and batch updates.
Cannot do it. Every query/insert/update is depend on the database's information. For example, we look up the DB for the client's information, if we cannot find his usage, we insert the usage into DB, otherwise we do update.
5. Close resources (Connections, Statements, ResultSets) when finished
Sure.
6. Select the fastest JDBC driver.
I don't know. I've search on the internet about the type of driver available and I am very confused. We use oracle.jdbc.driver.OracleDriver
and we use thin instead of oci, that's all I know. In addition, our program is a two-tier way ( java <-> oracle )
7. Turn off auto-commit
already done that.
Looking forwards to any help.
4. Try to combine queries and batch updates.
Cannot do it. Every query/insert/update is depend on the database's information. For example, we look up the DB for the client's information, if we cannot find his usage, we insert the usage into DB, otherwise we do update.
If you are doing that from the Java application you can improve performance by doing it in the database in one round-trip instead. There are a couple of ways:
1) Use a SQL MERGE statement
2) Write a stored procedure to do the insert or update logic and just call that from Java.
I assume from what you said that at the moment you have Java logic that works like this:
// Pseudocode
execute SQL 'select count(*) from mytable where id=?'
if result = 0 then
execute SQL 'insert into mytable (id,a,b,c) values (?,?,?,?)';
else
execute SQL 'update mytable set a=?, b=?, c=? where id=?';
end if;
That means 2 separate round-trips to the database: one to check whether the record exists, and another to either insert or update as appropriate.
Alternatives are:
1) Use a SQL MERGE statement:
// Pseudocode
execute SQL 'merge into mytable t using (select ? id, ? a, ? b, ? c from dual) s
on (t.id = s.id)
when matched then update set t.a = s.a, t.b = s.b, t.c = s.c
when not matched then insert (id, a, b, c)
values (s.id, s.a, s.b, s.c)';
The MERGE statement is a bit daunting at first, especially when like this you have to use Oracle's "dual" table.
2) Use a stored procedure:
// Pseudocode
execute SQL 'begin mytable_package.insert_or_update
(p_id => ?, p_a => ?, p_b => ?, p_c => ?); end;'
The stored procedure, in a package called mytable_package, would look something like
procedure insert_or_update (p_id mytable.id%type
,p_a mytable.a%type
,p_b mytable.a%type
,p_c mytable.a%type
)
is
begin
update mytable
set a = p_a, b = p_b, c = p_c
where id = p_id;
if sql%rowcount = 0 then
insert into mytable (id, a, b, c) values (p_id, p_a, p_b, p_c);
end if;
end;
Check your indexes!!! Bad update performance can be the result of a foreign key constraint where the index on the foreign key is missing on the referencing table.
4)Try to combine queries and batch updates.
Cannot do it. Every query/insert/update is depend on the database's information. For example, we look up the DB for the client's information, if we cannot find his usage, we insert the usage into DB, otherwise we do update.
Two things come to my mind:
Do the UPDATE statement and check the result of ExecuteUpdate(); only if it is zero, do the INSERT. Saves you one SELECT statement.
Always (possibly batch-)insert into an intermediary table, later use the MERGE statement to update your usage table.
5)Close resources (Connections, Statements, ResultSets) when finished
Keep the connection open as long as possible (i.e. permanently till shutdown of the server), prepare a PreparedStatement once and use it repeatedly.
Do a bit of aggregation before you write to the database. A cell phone user who generates a transaction now probably will generate another one within a few seconds. Use a hashtable to aggregate current usage and write it to the database after a minute or so.
Get hold of a copy of Professional Oracle Programming.
It seems a bit on the old side at 2005, but Oracle doesn't change drastically when it comes to optimising performance. I've got this book myself and have used it's advice to speed up seemingly intractable performance issues for many applications. Get it. Read it. Do it.
So what can you do while you wait for express delivery?
That should be enough to give you a firm grasp on what is failing and how to fix it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With