Hibernate Named Query Vs JDBC Query Performance [duplicate] - java

This question already has an answer here:
Hibernate, JDBC and Java performance on medium and big result set
(1 answer)
Closed 8 years ago.
My requirement is to get only the availability of records (not getting values). For this scenario,my problem is that what can be the better solution to improve performance between the JDBC query and the HQL Named query.
As I think,since named queries are loaded at the time of hibernate factories are loaded and therefore, it can be faster than jdbc.
Please not that This is not a normal HQL query, here I am asking about the Named Query.
Normal HQL and Named query can have different performance. Most of questions and answers are about normal HQL. My point here is the NAMED QUERY .

Hibernate is excellent . But most have problems with using criteria queries because they do not understand it should only be used with a small number of tables like 5 or less. If you are doing something in the enterprise level use HQL queries you have all the power of jdbc. Also the learning curve is high but once you learn nothing can compare.

I assume that your question is “which option you should choose between JDBC and Hibernate”.
First of all, With HQL you have your query ready with you and the query will not be going to be generated for every request. But In case of native SQL in hibernate , the query will be generated on demand if I’m not wrong.
Same with JDBC. If you use PreparedStatement , your query will be generated once in its life cycle. Almost both are same. By the way you have option to tell hibernate that you need the queries to be generated at start up of ORM engine or not. In JPA annotations you can use dynamic = true at #entity annotation.
If you already Hibernate/JPA infrastructure in your project make use of it else go with plain vanilla JDBC option.

Related

Storing a record with JOOQ shows different behavior on insert in h2 and MSSQL

When storing a record with jooq it generates different SQL for h2 and MSSQL, which makes it impossible to use quickperfs #ExpectInsert/#ExpectSelect annotations in test, since it counts differently. The generated SQL looks for H2 like:
select "ID" from final table (insert into...
and for MSSQL:
declare #result table ([ID] bigint); insert into ...
so in the first case quickperf does not count an insert but an select. So, why is the generated SQL so different? What are my options to solve this? Any hints are much appreciated.
I used the jooq store() method and insertInto() with no difference in the generated SQL.
The expectation of jOOQ (or any ORM) producing the exact same SQL for different SQL dialects is wrong. The whole point of abstracting over SQL is, in parts, to be able to generate SQL that "does the job".
In this case, it seems you're running some sort of statement that tries to implement RETURNING behaviour, where generated keys are to be fetched from the RDBMS after insertion. Both H2 and SQL Server have means to do this:
H2 implements the standard SQL data change delta table (FINAL TABLE (...))
SQL Server has an OUTPUT clause, but it has some limitations, including not being able to produce trigger generated values, so jOOQ generates a statement batch which fetches results into a in-memory temporary table.
You can find more details about this topic in this blog post about the many ways of returning data from SQL DML statements, on the jOOQ blog, which explains what jOOQ does behind the scenes, and why.
Your question "What are my options to solve this?" is harder to answer, because I'm not convinced your motivation here is reasonable: That of expecting identical SQL for both RDBMS.
Perhaps a much better question is: Do you really need H2 (as a test database product)? Here's jOOQ's take on this.

When Hibernate does not generate optimal query. How to make hibernate generate optimal query

While ORM frameworks like hibernate does simplify the activities of accessing and modifying data in RDBMS. And it's features like lazy loading, caching etc also help in better application performance when used properly.
But what I am thinking of is if the query generator or optimizer is not using the best query - say not following the proper ordering of tables during a join and not using the most suitable join strategy etc.
How can i optimize the query or say hibernate to generate a better query which is more optimal than the one it is generating by default.
(probably if I am not wrong, this question applies to other ORM frameworks like iBATIS etc also)
EDIT following answer from S. Bhattacharjee - I would also hope that Hibernate will generate the best optimal query. But on the other side even when using Oracle SQL executor in Oracle GUI, it's some time the case that the Optimizer DOES NOT use optimal plan. But I can influence it by writing the query more specifically. (don't ask me how it's done, if some one knows please indicate. I am no SQL expert. I need to analyse this case to ensure the systems flexibility and optimization's are not limited because of frameworks). So
CASE 1 - consider hibernate is not generating optimal query. So how to influence it to generate optimal query.
CASE 2 - hibernate is generating optimal query. But SQL engine is using a plan that is not optimal. Query and Plan (or execution) are different from my understanding. I am not sure if this is a valid case or not. So ignore if not applicable. But if anyone think this is a valid case even if they can't answer, plz leave a comment to bolster this point.
Next speaking about Hibernate query generator - another question pops in to my mind. Does Hibernate know about the Logical Structure of DB (I don't expect it to know the physical design anyway and may not be relevant to consider it here).
a) If it does know logical db design, how does it know about it.
b) if it does not know logical db design, then how can it be sure about the query being optimal.
Well, in my opinion hibernate generates a good and optimal query. Please be more clear on what grounds you are saying so, may be with an example? However if you want you may write your own SQL queries. Below is a very small example
Query query = session.createSQLQuery("select c.codename from
codes c where c.code = :paramcode")
.setParameter("paramcode", "900");
List result = query.list();

Named Query Or Native Query or Query Which one is better in performance point of view?

Which one is better among following(EJB 3 JPA)
//Query
a). getEntityManager().createQuery("select o from User o");
//Named Query where findAllUser is defined at Entity level
b). getEntityManager().createNamedQuery("User.findAllUser");**
//Native Query
c). getEntityManager().createNativeQuery("SELECT * FROM TBLMUSER ");
Please explain me which approach is better in which case?.
createQuery()
It should be used for dynamic query creation.
//Example dynamic query
StringBuilder builder = new StringBuilder("select e from Employee e");
if (empName != null) {
builder.append(" where e.name = ?");
}
getEntityManager().createQuery(builder.toString());
createNamedQuery()
It is like a constant variable which can be reused by name. You should use it in common database calls, such as "find all users", "find by id", etc.
createNativeQuery()
This creates a query that depends completely on the underlying database's SQL scripting language support. It is useful when a complex query is required and the JPQL syntax does not support it.
However, it can impact your application and require more work, if the underlying database is changed from one to another. An example case would be, if your development environment is in MySQL, and your production environment is using Oracle. Plus, the returned result binding can be complex if there is more than a single result.
For me, the better is obviously the first two one, that is JPQL Queries - the second meaning the entity manager will compile the queries (and validate them) while loading the persistence unit, while the first would only yield errors at execution time.
You can also get support in some IDE, and it support the object notation (eg: select b from EntityA a left join a.entityB b) and some other oddities introduced by the object-relational mapping (like collections, index, etc).
On the other hand, use Native queries in last resort in corner case of JPQL (like window function, such as select id, partition by (group_id) from table)
Native SQL is not necessarily faster than Hibernate/JPA Query. Hibernate/JPA Query finally also is translated into SQL. In some cases it can happen Hibernate/JPA does not generate the most efficient statements, so then native SQL can be faster - but with native SQL your application loses the portability from one database to another, so normally is better to tune the Hibernate/JPA Query mapping and the HQL statement to generate more efficient SQL statements. On the other side with native SQL you're missing the Hibernate cache - as a consequence in some cases native SQL can be slower than Hibernate/JPA Query.
I am not with performance, in most cases for the performance it is irrelevant if your load all columns or only the needed columns. In database access the time is lost when searching the row, and not when transferring the data into your application. When you read only the necessary columns.
Simple Answer:
1) createQuery() - When you want your queries to be executed at runtime.
2) createNamedQuery() - When you want to send common database calls like findBy<attribute>, findAll,..
3)createNativeQuery() - Used when you want your queries to be database vendor-specific. This brings a challenge of portability.
Named queries are the same as queries. They are named only to let them be reusable + they can be declared in various places eg. in class mappings, conf files etc. (so you can change query without changing actual code)
Native queries are just native queries. You have to do all the things that JPA Queries do for you eg. Binding and quoting values etc. + they use DBMP independent syntax (JPQL in your case) so changing database system (lets say from MySQL to Postgresql or H2) will require less work as it does not (not always) require to rewrite native queries.
Named Query:
All the required queries are written in one place related to that entity and they are differentiated by name and we can use them based on the name, no need to write entiry query each time just use the name of the query
For example:
#NamedQuery(name="User_detailsbyId",Query="from UserDetails where UserId=:UserId)

IBM DB2 9.7 Error code 840, select statement list is too large

We are using Hibernate with IBM DB2 9.7. The database gives error about Hibernate generated too large select statement list (including a lot of joins). The error code is 840. Can something be done to fix this? I know the generated select list is very long, but can Hibernate be set to split it into parts or something?
Edit: I reopened this since the problem seems to be a bit larger. So there is a JIRA issue (now rejected) at https://hibernate.onjira.com/browse/ANN-140.
So the problem is that with Hibernate Annotations, it is not possible to add discriminator with Join strategy. XML configuration however does support this.
Pavel nicely states the problem in the above link discussion like this:
"It would be nice to see how the problem with the multiple joins is faced when the
underlying DB has restriction on the number of joins one can execute in a single SQL?
For instance MySQL seems to allow only 31 joins. What happens if the class hierarchy
has more than 31 sub-classes?"
An the above is the very problem I am having. We are using annotations and the subclasses are quite a few, creating massive amounts of joins, breaking the DB2 statement.
Any comments on this? I could not find a direct solution either.
Hibernate has few fetching strategies to optimize the Hibernate generated select statement, so that it can be as efficient as possible. The fetching strategy is declared in the mapping relationship to define how Hibernate fetch its related collections and entities.
Fetching Strategies
There are four fetching strategies
fetch-”join” = Disable the lazy loading, always load all the collections and entities.
fetch-”select” (default) = Lazy load all the collections and entities.
batch-size=”N” = Fetching up to ‘N’ collections or entities, Not record.
fetch-”subselect” = Group its collection into a sub select statement.
For detail explanation, you can check on the Hibernate documentation.

Hibernate Criteria Limit mechanism?

Hibernate Criteria support provides a setMaxResults() method to limit the results returned from the db.
I can't find any answer to this in their documentation - how is this implemented? Is it querying for the entire result set and then returning only the request number? Or is it truly limiting the query on the database end (think LIMIT keyword as in mySql).
This is important because if a query could potentially return many many results, I really need to know if the setMaxResults() will still query for all the rows in the database (which would be bad).
Also - if its truly limiting the number of rows on the database end, how is it achieving this cross-db (since I don't think every rdbms supports a LIMIT functionality like mySql does).
Hibernate asks the database to limit the results returned by the query. It does this via the dialect, which uses whatever database-specific mechanism there is to do this (so for SQL Server it will do somthing like "select top n * from table", Oracle will do "select * from table where rownum < n", MySQL will do "select * from table limit n" etc). Then it just returns what the database returns.
The class org.hibernate.dialect.Dialect contains a method called supportsLimit(). If dialect subclasses override this method, they can implement row limit handling in a fashion native to their database flavor. You can see where this code is called from in the class org.hibernate.loader.Loader which has a method titled prepareQueryStatement, just search for the word limit.
However, if the dialect does not support this feature, there is a hard check in place against the ResultSet iterator that ensures Java object (entity) results will stop being constructed when the limit is reached. This code is also located in Loader as well.
I use both Hibernate and Hibernate Search and without looking at the underlying implementation I can tell you that they definitely do not return all results. I have implemented the same query returning all results and then changed it to set the first result and max results (to implement pagination) and the performance gains were massive.
They likely use dialect specific SQL for this, e.g. LIMIT in MySQL, ROWNUM in Oracle. Your entity manager is aware of the dialect that you are using so this is simple.
Lastly if you really want to check what SQL Hibernate is producing for this query, just set the "show_sql" property to true when you create your entity manager / factory and it spits out all the SQL it is running to the console.
HQL does not suppport a limitation inside a query like in SQL, only the setMaxResults() which you also found.
To find out if it transform the setMaxResults() into a LIMIT query, you can turn on your SQL logging.
I know Question is bit old. But yes setMaxResults() is truly limiting the number of rows on the database end.
If you really look into your Hibernate SQL output, you can find the following SQL statement has been appended to your query.
limit ?

Categories

Resources