#DevoxxFR
“More than half of application performance bottlenecks originate
in the database”
AppDynamics - http://www.appdynamics.com/database/
#DevoxxFR
• Connection acquisition time
• Data access logic (e.g. entity state transitions)
• Statements submission time
• Statements execution time
• Result set fetching time
• Idle time prior to releasing the database connection
𝑇 = 𝑡𝑎𝑐𝑞 + 𝑡𝑑𝑎𝑙 + 𝑡𝑟𝑒𝑞 + 𝑡𝑒𝑥𝑒𝑐 + 𝑡𝑟𝑒𝑠 + 𝑡𝑖𝑑𝑙𝑒
#DevoxxFR
• Connection providers
• Identifier generators
• Relationships
• Batching
• Fetching
• Caching
#DevoxxFR
• Connections acquired lazily
• The shorter the transaction lifespan, the higher the transaction throughput
#DevoxxFR
10 50 100 500 1000 5000 10000
0
200
400
600
800
1000
1200
1400
Statement count
Tim
e (
ms)
After statement After transaction
#DevoxxFR
<property name="hibernate.connection.release_mode" value="after_transaction"/>
• For JTA (e.g. Java EE), try this setting:
#DevoxxFR
• AUTO (IDENTITY or SEQUENCE)
• IDENTITY
• SEQUENCE
• TABLE
𝑇 = 𝑡𝑎𝑐𝑞 + 𝑡𝑑𝑎𝑙 + 𝑡𝑟𝑒𝑞 + 𝑡𝑒𝑥𝑒𝑐 + 𝑡𝑟𝑒𝑠 + 𝑡𝑖𝑑𝑙𝑒
#DevoxxFR
• Default for Oracle and PostgreSQL when using AUTO
• May use roundtrip optimizers: hi/lo, pooled, pooled-lo
• Hibernate 5 uses the enhanced sequence generator by default
<property name="hibernate.id.new_generator_mappings" value="true"/>
#DevoxxFR
• Uses row-level locks and a separate transaction/connection
• May use roundtrip optimizers: hi/lo, pooled, pooled-lo
• Hibernate 5 uses the enhanced table generator by default
<property name="hibernate.id.new_generator_mappings" value="true"/>
#DevoxxFR
• Both generators use an increment size of 100
1 2 4 8 16
0
200
400
600
800
1000
1200
Thread count
Tim
e (
ms)
Sequence Table
#DevoxxFR
<property name="hibernate.jdbc.batch_size" value="10"/>
• SessionFactory configuration
• Plan to support Session-level batch size configuration
𝑇 = 𝑡𝑎𝑐𝑞 + 𝑡𝑑𝑎𝑙 + 𝑡𝑟𝑒𝑞 + 𝑡𝑒𝑥𝑒𝑐 + 𝑡𝑟𝑒𝑠 + 𝑡𝑖𝑑𝑙𝑒
#DevoxxFR
1 10 20 30 40 50 60 70 80 90 100 1000
0
200
400
600
800
1000
1200
1400
1600
Batch size
Tim
e (
ms)
DB_A DB_B DB_C DB_D
#DevoxxFR
1 10 20 30 40 50 60 70 80 90 100 1000
0
100
200
300
400
500
600
700
Batch size
Tim
e (
ms)
DB_A DB_B DB_C DB_D
#DevoxxFR
1 10 20 30 40 50 60 70 80 90 100 1000
0
200
400
600
800
1000
1200
Batch size
Tim
e (
ms)
DB_A DB_B DB_C DB_D
#DevoxxFR
<property name="hibernate.order_inserts" value="true"/>
<property name="hibernate.order_updates" value="true"/>
• Plan to support delete statement ordering too
#DevoxxFR
<property name="hibernate.jdbc.batch_versioned_data" value="true"/>
• Enabled by default in Hibernate 5
• Disabled in Hibernate 3 and 4, Oracle 8i, 9i, and 10g dialects.
#DevoxxFR
• JDBC fetch size
• JDBC ResultSet size
• DTO vs Entity queries
• Association fetching
𝑇 = 𝑡𝑎𝑐𝑞 + 𝑡𝑑𝑎𝑙 + 𝑡𝑟𝑒𝑞 + 𝑡𝑒𝑥𝑒𝑐 + 𝑡𝑟𝑒𝑠 + 𝑡𝑖𝑑𝑙𝑒
#DevoxxFR
• Oracle – Default fetch size is 10
• SQL Server – Adaptive buffering
• PostgreSQL, MySQL – Fetch the whole ResultSet at once
• SessionFactory setting:
<property name="hibernate.jdbc.fetch_size" value="100"/>
#DevoxxFR
• Query-level fetch size setting
List<PostCommentSummary> summaries = entityManager.createQuery("select new PostCommentSummary( " +" p.id, p.title, c.review ) " +"from PostComment c " +"join c.post p")
.setHint(QueryHints.HINT_FETCH_SIZE, fetchSize)
.getResultList();
#DevoxxFR
• Hibernate SQL-level limiting (works for native queries too!)
List<PostCommentSummary> summaries = entityManager.createQuery("select new PostCommentSummary( " +" p.id, p.title, c.review ) " +"from PostComment c " +"join c.post p")
.setFirstResult(pageStart)
.setMaxResults(pageSize)
.getResultList();
#DevoxxFR
• 100k Post(s) and + 1M PostComment(s) vs 100 entries
Fetch all Fetch limit
0
500
1000
1500
2000
2500
3000
3500
4000
4500
5000
Tim
e (
ms)
DB_A DB_B DB_C DB_D
#DevoxxFR
SELECT *FROM post_comment pcINNER JOIN post p ON p.id = pc.post_idINNER JOIN post_details pd ON p.id = pd.id
SELECT pc.versionFROM post_comment pcINNER JOIN post p ON p.id = pc.post_idINNER JOIN post_details pd ON p.id = pd.id
• Selecting all columns vs selecting a custom projection
#DevoxxFR
• 100 Post(s), 100 PostDetail(s) , and 1000 PostComment(s)
All columns Custom projection
0
5
10
15
20
25
30
Tim
e (
ms)
DB_A DB_B DB_C DB_D
#DevoxxFR
• Read-only views
• Tree structures (Recursive CTE)
• Paginated Tables
• Analytics (Window functions)
#DevoxxFR
• Writing data
• Web flows / Multi-request logical transactions
• Application-level repeatable reads
• Detached entities / PersistenceContextType.EXTENDED
• Optimistic concurrency control (e.g. version, dirty properties)
#DevoxxFR
• Default to FetchType.LAZY
• Fetch directive in JPQL/Criteria API queries
• Entity graphs / @FetchProfile
• LazyInitializationException
#DevoxxFR
<property name="hibernate.enable_lazy_load_no_trans" value="true"/>
• “Band aid” for LazyInitializationException
• One temporary Session/Connection for every lazily fetched association
#DevoxxFR
“There are only two hard things in Computer Science: cache
invalidation and naming things.”
Phil Karlton
#DevoxxFR
• Complement entity caching
• Store only entity identifiers
• Read-Through
• Invalidation-based (Consistency over Performance)
Top Related