From eaaf1cf431473dabad7f2109b14d7b6d8a9d7b04 Mon Sep 17 00:00:00 2001
From: Rawley mod_perl in Docker
- By enabling
logging.level.org.hibernate.SQL=DEBUG and logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE,
+ By enabling logging.level.org.hibernate.SQL=DEBUG and logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
you're able to see the ridiculous number queries JPA is executing, they're un-countable, there's so many!! How can we fix this?
- If you're thinking of using
@Batch(100), it could work, only issue is JPA will batch each relationship, so each of our tables will still require
- n/100 calls where n is the number of rows with relationships. So theoretically a 100x speed bump right? Well, it's actually more
+ If you're thinking of using @Batch(100), it could work, only issue is JPA will batch each relationship, so each of our tables will still require
+ n/100 calls where n is the number of rows with relationships. So theoretically a 100x speed bump right? Well, it's actually more
like a 33x performance bump, since you still have the overhead of making the database connections, and need to get a lock every time you select. Doing this we moved to around
3-5 minutes depending on load per large call. This however, was still unacceptable.
- What if instead we just forced JPA to use
OUTER JOIN? Isn't that exactly what the ANSI SQL wizards would tell you to do?
+ What if instead we just forced JPA to use OUTER JOIN? Isn't that exactly what the ANSI SQL wizards would tell you to do?
Obviously, this is the solution, one single connection, 1 lock, and let the B-Tree optimizations inside of the database handle all of this ugliness for us.
- To do this you need to use something called @EntityGraph
- on your JPA repository, what this does is forces JPA to use a OUTER JOIN
+ To do this you need to use something called @EntityGraph
+ on your JPA repository, what this does is forces JPA to use a OUTER JOIN
to join relationships. This even works on nested entities, say I have Entity A with a child B which also has a One-to-Many on C, all you need to do
- is add the relationship to the entity graph with the @NamedEntityGraph annotation, then provide it with a few nice args like name,
+ is add the relationship to the entity graph with the @NamedEntityGraph annotation, then provide it with a few nice args like name,
and attributeNodes which will point to your sub entity. Then finally on your JPA repository call you stitch the entity graph back together.
-
@Repository
@@ -49,7 +48,6 @@ public interface ARepository extends JpaRepository, JpaSpecificationExe
}
-
After applying these, the query time went down from 15 minutes to ... *drum-roll* ... 3 seconds. So please, for the love of all that is computationally efficient, force your JPA to use
OUTER JOIN, or even roll your own SQL, ORM's really are one of the biggest trade-offs, and they really can bite you. This is why tend to