+ All Categories
Home > Software > High-Performance Hibernate Devoxx France 2016

High-Performance Hibernate Devoxx France 2016

Date post: 14-Feb-2017
Category:
Upload: vlad-mihalcea
View: 7,589 times
Download: 1 times
Share this document with a friend
49
#DevoxxFR
Transcript

#DevoxxFR

#DevoxxFR

• Hibernate Developer Advocate

• vladmihalcea.com

• @vlad_mihalcea

#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

#DevoxxFR

𝑇 = 𝑡𝑎𝑐𝑞 + 𝑡𝑑𝑎𝑙 + 𝑡𝑟𝑒𝑞 + 𝑡𝑒𝑥𝑒𝑐 + 𝑡𝑟𝑒𝑠 + 𝑡𝑖𝑑𝑙𝑒

#DevoxxFR

• Connections acquired lazily

• The shorter the transaction lifespan, the higher the transaction throughput

#DevoxxFR

#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 SQL Server and MySQL when using AUTO

• Disables JDBC batch inserts

#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

1 5 10 50

0

0.05

0.1

0.15

0.2

0.25

0.3

0.35

0.4

0.45

Sequence increment size

Tim

e (

ms)

#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

1 5 10 50

0

0.5

1

1.5

2

2.5

3

Table increment size

Tim

e (

ms)

#DevoxxFR

• Identity makes no use of batch inserts

• Table generator using an increment size of 100

#DevoxxFR

1 2 4 8 16

0

500

1000

1500

2000

2500

Thread count

Tim

e (

ms)

Identity Table

#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

𝑇 = 𝑡𝑎𝑐𝑞 + 𝑡𝑑𝑎𝑙 + 𝑡𝑟𝑒𝑞 + 𝑡𝑒𝑥𝑒𝑐 + 𝑡𝑟𝑒𝑠 + 𝑡𝑖𝑑𝑙𝑒

#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

1 10 100 1000 10000

0

100

200

300

400

500

600

Fetch size

Tim

e (m

s)

DB_A DB_B DB_C DB_D

#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

#DevoxxFR

“You can turn a Lazy into an Eager, but you cannot turn an

Eager into a Lazy”

#DevoxxFR

• Default to FetchType.LAZY

• Fetch directive in JPQL/Criteria API queries

• Entity graphs / @FetchProfile

• LazyInitializationException

#DevoxxFR

#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

𝑇 = 𝑡𝑎𝑐𝑞 + 𝑡𝑑𝑎𝑙 + 𝑡𝑟𝑒𝑞 + 𝑡𝑒𝑥𝑒𝑐 + 𝑡𝑟𝑒𝑠 + 𝑡𝑖𝑑𝑙𝑒

#DevoxxFR

#DevoxxFR

“There are only two hard things in Computer Science: cache

invalidation and naming things.”

Phil Karlton

#DevoxxFR

#DevoxxFR

• Complement entity caching

• Store only entity identifiers

• Read-Through

• Invalidation-based (Consistency over Performance)

#DevoxxFR

#DevoxxFR

https://leanpub.com/high-performance-java-persistence

𝑇 = 𝑡𝑎𝑐𝑞 + 𝑡𝑑𝑎𝑙 + 𝑡𝑟𝑒𝑞 + 𝑡𝑒𝑥𝑒𝑐 + 𝑡𝑟𝑒𝑠 + 𝑡𝑖𝑑𝑙𝑒


Recommended