I have encountered a case where the performance disparity between JPQL
and SQL queries seems unreasonable when fetching a large number of
results (5000+). Have a look at the log below:
JPQL Query:
SELECT led FROM LintEntryDetails led WHERE
led.parentJob.id
= :parentJob AND led.entry = :file
13:35:04,250 DEBUG ~ select lintentryd0_.id as id219_,
lintentryd0_.issue_category as issue2_219_, lintentryd0_.comments as
comments219_, lintentryd0_.entry as entry219_, lintentryd0_.issue as
issue219_, lintentryd0_.itemID as itemID219_, lintentryd0_.LINTJOB_ID
as LINTJOB10_219_, lintentryd0_.severity as severity219_,
lintentryd0_."string" as string8_219_, lintentryd0_.substring as
substring219_ from LintEntryDetails lintentryd0_ where
lintentryd0_.LINTJOB_ID=? and lintentryd0_.entry=?
13:35:22,015 INFO ~ jpql query over, fetched 7267 results
Total time ~18 seconds
13:35:22,015 DEBUG ~ SELECT * FROM LINTENTRYDETAILS WHERE LINTJOB_ID=1
AND LINTENTRYDETAILS.ENTRY='myfile.txt'
13:35:22,718 INFO ~ Native query over, fetched 7267 results
Total time ~700ms
This is the underlying code for the JPQL:
List<LintEntryDetails> entryDetails =
LintEntryDetails.find(query.toString())
.bind("parentJob", parentJobId)
.bind("file", filename)
.fetch();
And for the native query:
Query nativeQuery = JPA.em().createNativeQuery("SELECT * FROM
LINTENTRYDETAILS WHERE LINTJOB_ID=1 AND
LINTENTRYDETAILS.ENTRY='myfile.txt'");
List results = nativeQuery.getResultList();
The actual LintEntryDetails model contains only simple fields and one
@ManyToOne field that I explicitly set the FetchType to LAZY, and you
can see from the resulting hibernate query that nothing is being
joined, so that can't be the source of abysmal performance.
My question is, then, is this normal, and is the overhead introduced
by mapping the retrieved fields onto the domain models? If so, can one
justify using JPA/Hibernate queries for anything exceeding a handful
of rows? Thanks in advance for any insights you might have!