We are using hibernate named query as follows :
named_query : Select this_ from TableA this_ where this_.id in( select max(id) from TableA where COLA is null group by COLB ) and rownum=1
Query query = getNamedQuery("nq.select.DirtySubject.onMaxDirtySubjectRecId");
List<SomeObject> objectList = query.list();
The query has been flagged by the DBAs and the comments verbatim are as follows
These indicate the SQL statements that are consuming the most parsing
resources every time they execute.
The SQL statements that appear in
this report are probably being reparsed. Excessively-parsed SQL
statements should be optimized to reduce their parsing frequency. This
involves using bind variables and identical statement syntax and case,
in order to be able to reuse any previously-parsed statements in the
SQL cache.
Examine these queries to see if any SQL optimization is
possible and reasonable.
Other material facts:
This query is part of a polling logic and gets fired repeatedly.
Database:Oracle 11G
Technology stack : Java,Hibernate,Tomcat,Linux,Oracle 11G
Questions:
1: Behind the scene- Hibernate will be using Prepared statement - correct ?
2: What can we possibly do more from the application side - to avoid re-parsing of this query ?
3: Anything we can do on the Database server to avoid re-parsing ?
The comment talks about parsing resources (in contrast to execution time/resources), but the statement itself does not really look that difficult to parse. The most interesting information would be the execution plan. I assume that the query is always the same (but the comment contains the word "probably").
As for question 1:
If you want to make sure that prepared statements do help, you can try to run the same query without Hibernate - just plain java.sql, PreparedStatement.
If so, there is a Hibernate prepared statement cache, but I have never used it.
As for question 2:
If this is your hotspot, you can use "direct SQL" with Hibernate (if it and your connection pool allows the caching of prepared statements) or even without it: Then you have full control.
As for question 3: Have a look on Oracle 11g result cache.
Related
I am facing an ORA:7445 issue with auto sql tuning advisor. Auto sql tuning advisor keeps failing with
ORA:7445
while it's tries to tune a particular SQL.
Is there any way to skip this sql statement from auto sql tuning advisor job?
The simplest way to avoid the Automatic SQL Tuning Advisor may be to convert the query into a form that is not supported by the program.
According to the "Automatic SQL Tuning" chapter of the "Database Performance Tuning Guide":
The database ignores recursive SQL and statements that have been tuned
recently (in the last month), parallel queries, DML, DDL, and SQL
statements with performance problems caused by concurrency issues.
If the query select * from dba_objects was causing problems, try re-writing it like this:
select * from dba_objects
union all
--This query block only exists to avoid the Automatic SQL Tuning Advisor.
select /*+ parallel(dba_objects 2) */ * from dba_objects
where 1=0;
It is now a "parallel query" although it will not truly run in parallel because of the 1=0. I haven't tested this, and I imagine it will be difficult for you to test, because you'll need to flush the existing AWR data to prevent the errors.
This is one of the reasons why I usually disable the Automatic SQL Tuning Advisor. I like the idea of it, but in practice I've literally never seen the tuning advisor provide useful information. All it has ever done for me is generate alerts.
In theory,the package DBMS_AUTO_SQLTUNE contains the parameters BASIC_FILTER, OBJECT_FILTER, and PLAN_FILTER. I assume one of those could be useful but I don't think they are implemented yet. I can't find any references to them on Google or My Oracle Support. And when I entered random text for the values there were no errors.
Ideally we would look up every ORA-00600 and ORA-07445 error, create an SR, and fix the underlying problem. But who has time for that? when you encounter a database "bug", the best solution is usually to avoid it as quickly as possible.
My query that I put into a prepared statement is:
select *
from ( select seq, audit_ts, message_type
from log2
where 1 = 1
and message_type in ('SOURCE', 'DEST')
order by seq desc )
where ROWNUM <= ?
When I run the query in my application, I get:
java.sql.SQLSyntaxErrorException: ORA-00907: missing right parenthesis
EDIT: Here is the java executing the query. I am trying to return a set of search results, so the prefix contains the SELECT statement and then I can have any number of suffixes (in this excerpt "AUDIT_LOG_SEARCH2") which are the parameterized WHERE clauses based on the user search:
StringBuffer query = new StringBuffer(300);
query.append(dbAdapter.getQuery("AUDIT_LOG_ENTRY_PREFIX"));
query.append(dbAdapter.getQuery("AUDIT_LOG_SEARCH2"));
// Insert parameters to complete the sql prepared statement
PreparedStatement ps = _dbConn.prepareStatement(query.toString());
ResultSet rs = ps.executeQuery();
But the query runs fine when I run it separately in SQL Developer. The query was originally created for Postgres, then updated for Oracle. Any tips?
You need to set the variables into the preparedStatement before executing.
PreparedStatement ps = _dbConn.prepareStatement(query.toString());
ps.setInt(1, 10);
Please post what query.toString() gives you if that doesn't work. Not query, but query.toString()
What are you doing in your:
// Insert parameters to complete the sql prepared statement
Are you using correctly the methods ps.setString... or whatever? Or are you just replacing the question marks? the second might be corrupting your query.
Based on #AlexPoole and #EdGibbs comments, I decided to add a bunch more debug statements. It turns out the method was being recursively called with a different sql "suffix" later on in the program if certain conditions were met. The suffix was not updated with the necessary parenthesis for the new ROWNUM wrapping the statement. So although the ORA-00907 can be thrown for many different formatting problems, it was in fact a right parenthesis that was causing me problems :P
The prefix and suffix seems like a weird pattern in this code base for creating sql queries. I'm thinking of getting rid of this and refactoring so queries don't have to be built like that. Any advice??
So for anyone else who runs into this Oracle error, I would suggest logging the sql statement you are generating and play around with it in SQL Developer. If it works in there, but not in your application, your code is probably doing something funky :P
I have a complex Oracle view which takes around ~ 2 - 3 seconds to execute.
I'm trying to insert values from the Oracle view into a table.
I'm using JdbcTemplate BatchUpdate() to insert multiple values into the table.
In BatchUpdate(), PreparedStatement is used to set values.
Will using a Oracle view, cause any performance issue?
By using PreparedStatement, SQL statements are precompiled. But in case of VIEW, will the view be executed each time the insert query is fired ?
Views are just SQL-statements. They are not slower or faster than the underlying SQL-query.
However, when using complex views (multi-table joins and aggregation) built on-top of other complex views the optimizer may get confused and tries to outsmart itself, leading to really bad execution plans. The problems tend to be even worse if you don't have constraints, referential integrity in place.
A final note is that if you are merely pulling data out of the database to stuff it back in, you would probably achieve better performance doing the entire operation in the database instead. For an example, let's say you pull "order lines" from the database and then updates the "order header" with an "Order Total Qty". In this case you should probably do something like below instead:
merge
into order_header h
using (select order_id, sum(order_qty) as order_total_qty
from order_line
group by order_id
) l
on (h.order_id = l.order_id)
when matched then
update
set h.order_total_qty = l.order_total_qty;
We are using Hibernate 3 with WebSphere v6 and DB2. We are having strange issue with wrong SQL prepared statements issued by Hibernate and causing syntax issues.
Good query issued by Hibernate:
SELECT * FROM rocc.Transaction t WHERE t.status_cd = 0 and
t.application_cd = ? order by coalesce(t.priority,0) fetch first 25
rows only
Same query issued by Hibernate incorrectly sometimes:
SELECT * FROM rocc.Transaction t WHERE t.status_cd = ? AND
t.application_cd = ? ORDER BY COALESCE(t.priority,?) FETCH first
? ROWS ONLY
It is replacing values(zero) with question mark and changing font of the keywords to uppercase (it does not matter, but mentioning here). It also changed the number 25 in fetch clause with question mark.
What is causing with the wrong prepared statement issued by Hibernate sometimes?
Hibernate is calling WSJdbcPreparedStament.executeQuery method.
This is the normal behavior of the preparedStatement on JDBC, it substitutes the parameters on the query with ?, this also helps the database to construct a optimized access plan for your query. Hibernate is just automating this.
Jdbc Reference or how we used to to before we have hibernate.
select max(Key) from MyTable with(nolock)
I have this T-SQL statement but need to use one statement for both SQL Server and Oracle as well, of course the “with (nolock)” is not recognised by Oracle. Is there a way having this statement that will run on both databases. By either an Oracle ignoring the “with (nolock)” or only Sqlserver using this part of the statement or a way or coded that both with understand.
The reason why I am using No lock is because multiple users are accessing the same table and I need to find the max value during the transactions.
Oracle does things a bit differently so I do not have to worry about table locks.
Your queries are doing different things. What are the semantics of the query supposed to be? Is it supposed to return max(Key) including the effect of uncommitted transactions as your SQL Server version indicates? If so
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
select max(Key)
from MyTable;
Is the same semantics. The syntax should work fine on both AFAIK.
If instead you want the last committed max(Key) you would need to change the SQL Server database to use read committed snapshot isolation by default so it behaves more similarly to Oracle. Or alternatively you could achieve similar semantics with ROWLOCK,READPAST hints but then you are back to needing two different queries.