Effiziente persistierung

55
Effiziente Persistierung mit Hibernate www.thoughts-on-java.org

Transcript of Effiziente persistierung

Page 1: Effiziente persistierung

www.thoughts-on-java.org

Effiziente Persistierung

mit Hibernate

Page 2: Effiziente persistierung

Thor

ben

Jans

sen • Independent author and trainer

• Senior developer and architect @ Qualitype GmbH

• CDI 2.0 expert group member

• Twitter: @thjanssen123• Blog: www.thoughts-on-java.org

www.thoughts-on-java.org

Page 3: Effiziente persistierung

Performance

www.thoughts-on-java.org

Page 4: Effiziente persistierung

Perfo

rman

ce • Recognize performance problems as early as possible

• Typical causes for performance problems

• Solving performance problems

www.thoughts-on-java.org

Page 5: Effiziente persistierung

Hibernate Statistics

www.thoughts-on-java.org

Page 6: Effiziente persistierung

Hibe

rnat

e St

atist

ics• Activate via system property

• hibernate.generate_statistics = true

• Configure logging

• org.hibernate.stat = DEBUG

www.thoughts-on-java.org

Page 7: Effiziente persistierung

Hibe

rnat

e St

atist

ics08:24:10,916 DEBUG [org.hibernate.stat.internal.ConcurrentStatisticsImpl] (default task-1) HHH000117: HQL: SELECT a FROM Author a WHERE a.lastName = :lastName, time: 6ms, rows: 1

www.thoughts-on-java.org

Time spend for this query

Number of returned rows

Page 8: Effiziente persistierung

Hibe

rnat

e St

atist

ics08:08:04,960 INFO [org.hibernate.engine.internal.StatisticalLoggingSessionEventListener] (default task-2) Session Metrics { 1191522 nanoseconds spent acquiring 4 JDBC connections; 433875 nanoseconds spent releasing 4 JDBC connections; 4404058 nanoseconds spent preparing 6 JDBC statements; 12458725 nanoseconds spent executing 6 JDBC statements; 0 nanoseconds spent executing 0 JDBC batches; 0 nanoseconds spent performing 0 L2C puts; 0 nanoseconds spent performing 0 L2C hits; 0 nanoseconds spent performing 0 L2C misses; 586896 nanoseconds spent executing 1 flushes (flushing a total of 2 entities and 2 collections); 39434974 nanoseconds spent executing 1 partial-flushes (flushing a total of 2 entities and 2 collections)

www.thoughts-on-java.org

Number of SQL statementsCache

usage

Time spend for SQL state-ments

Page 9: Effiziente persistierung

Typical causes for performance problems

www.thoughts-on-java.org

Page 10: Effiziente persistierung

Typi

cal C

ause

s • Slow SELECT statements

• Wrong FetchType

• Load same data multiple times

• Delete or edit records one by one

• Put logic into the application instead of the database/query

www.thoughts-on-java.org

Page 11: Effiziente persistierung

Slow SELECT-statements

www.thoughts-on-java.org

Page 12: Effiziente persistierung

Slow

SEL

ECTs • In general no „real“ JPA or Hibernate problem

• Check generated SQL

• Check execution plan of the statement

• Check indexes

• Optimize SELECT statement

• Consider to use a native querywww.thoughts-on-java.org

Page 13: Effiziente persistierung

Nativ

e Qu

ery • Reasons to use native queries:

• JPQL supports only a subset of SQL

• Database specific features

• Native queries return an Object[] for each row

• Needs to be mapped programmatically or declaratively

www.thoughts-on-java.org

Page 14: Effiziente persistierung

Resu

ltSet

Map

ping

• Declarative mapping of query results

www.thoughts-on-java.org

@SqlResultSetMapping(name = "myResultMapping ",entities = {@EntityResult(...), …},classes = {@ConstructorResult (…), …},columns = {@ColumnResult(…), …}

)

this.em.createNativeQuery(“Select …", "myResultMapping")

Page 15: Effiziente persistierung

Resu

ltSet

Map

ping

www.thoughts-on-java.org

@SqlResultSetMapping(name = "myResultMapping",entities = {@EntityResult(

entityClass = Author.class,fields = {

@FieldResult(name = "id", column = „autId"),…}

), …},

classes = {@ConstructorResult (…), …},columns = {@ColumnResult(…), …}

)

Page 16: Effiziente persistierung

Resu

ltSet

Map

ping

www.thoughts-on-java.org

@SqlResultSetMapping(name = "myResultMapping",entities = {@EntityResult(...), …},classes = {@ConstructorResult(

targetClass = BookPublisherValue.class,columns = {

@ColumnResult(name = "title"), …}

), …},

columns = {@ColumnResult(…), …})

Page 17: Effiziente persistierung

Resu

ltSet

Map

ping

www.thoughts-on-java.org

@SqlResultSetMapping(name = "myResultMapping",entities = {@EntityResult(...), …},classes = {@ConstructorResult(...), …},columns = {@ColumnResult(

name = "bookCount", type = Long.class),

…},)

Page 18: Effiziente persistierung

FetchType

www.thoughts-on-java.org

Page 19: Effiziente persistierung

Fetc

hTyp

e • Defines when the relationship will be fetched

• Static definition in entity mapping

www.thoughts-on-java.org

@ManyToMany(mappedBy="authors", fetch = FetchType.EAGER)private Set<Book> books;

Page 20: Effiziente persistierung

Fetc

hTyp

e• Lazy

• Relationship gets loaded at first access

• Default for to-many relationships

• Eager

• Loads relationships immediately

• Default for to-one relationshipswww.thoughts-on-java.org

Page 21: Effiziente persistierung

Reco

mm

enda

tion

s• To-many relationships

• Stick to the default mapping (FetchType.LAZY)

• Use eager fetching for specific queries, if required

• To-one relationships

• Check individually

• Default is fine in most of the caseswww.thoughts-on-java.org

Page 22: Effiziente persistierung

Query Specific Fetching

www.thoughts-on-java.org

Page 23: Effiziente persistierung

N+1

Sele

ct? • Most common cause for performance problems

• Lazy fetching of related entities creates too many queries

www.thoughts-on-java.org

List<Author> authors = this.em.createQuery("SELECT a FROM Author a",

Author.class).getResultList();

for (Author a : authors) {System.out.println("Author " + a.getFirstName() + " " +

a.getLastName() + " wrote " + a.getBooks().size() + “ Books.”));

}

Page 24: Effiziente persistierung

Quer

y sp

ecifi

c fe

tchi

ng• Fetch all required entities with one query

• Fetch Joins

• @NamedEntityGraph

• EntityGraph

www.thoughts-on-java.org

Page 25: Effiziente persistierung

Appl

icatio

n

www.thoughts-on-java.org

Page 26: Effiziente persistierung

Fetch Join

www.thoughts-on-java.org

Page 27: Effiziente persistierung

Fetc

h Jo

in • Use JOIN FETCH instead of JOIN in JPQL query

www.thoughts-on-java.org

List<Author> authors = this.em.createQuery("SELECT DISTINCT a FROM Author a JOIN FETCH a.books b", Author.class).getResultList();

Page 28: Effiziente persistierung

Fetc

h Jo

in• Advantages

• Relationships gets loaded in same query

• Disadvantages

• Requires a special query for each use case

• Creates cartesian product

www.thoughts-on-java.org

Page 29: Effiziente persistierung

NamedEntityGraph

www.thoughts-on-java.org

Page 30: Effiziente persistierung

Nam

edEn

tityG

rap

h• Introduced in JPA 2.1

• Declaratively defines a graph of entities which will be loaded

• Graph is query independent

www.thoughts-on-java.org

Page 31: Effiziente persistierung

Nam

edEn

tityG

rap

h• Define NamedEntityGraph

www.thoughts-on-java.org

@NamedEntityGraph(name = "graph.AuthorBooksReviews",

attributeNodes = @NamedAttributeNode(value = "books")

)

@NamedEntityGraph(name = "graph.AuthorBooksReviews",

attributeNodes = @NamedAttributeNode(value = "books", subgraph = "books"),

subgraphs = @NamedSubgraph(

name = "books", attributeNodes = @NamedAttributeNode("reviews")

))

Page 32: Effiziente persistierung

Nam

edEn

tityG

rap

h• Provide entity graph es hint

www.thoughts-on-java.org

EntityGraph graph = this.em.getEntityGraph("graph.AuthorBooks");

this.em.createQuery("SELECT DISTINCT a FROM Author a") .setHint("javax.persistence.loadgraph", graph);

Page 33: Effiziente persistierung

Nam

edEn

tityG

rap

h• Fetch graph

• Eager loading for all elements of the graph• Lazy loading for all other attributes

• Load graph• Eager loading for all elements of the graph• Loads all other attributes with their defined

FetchType

• Hibernate always uses a load graph• HHH-8776

www.thoughts-on-java.org

Page 34: Effiziente persistierung

Nam

edEn

tityG

rap

h• Advantages

• Query specific EAGER loading

• Definition of the graph is independent of the query

• Disadvantages

• Creates cartesian product

www.thoughts-on-java.org

Page 35: Effiziente persistierung

EntityGraph

www.thoughts-on-java.org

Page 36: Effiziente persistierung

Entit

yGra

ph• Introduced in JPA 2.1

• Dynamic version of @NamedEntityGraph

• Definition via Java API

• Graph is query independent

www.thoughts-on-java.org

Page 37: Effiziente persistierung

Entit

yGra

ph• Define and use EntityGraph

www.thoughts-on-java.org

EntityGraph graph = this.em.createEntityGraph(Author.class);Subgraph<Book> bookSubGraph = graph.addSubgraph(Author_.books);bookSubGraph.addSubgraph(Book_.reviews);

this.em.createQuery("SELECT DISTINCT a FROM Author a") .setHint("javax.persistence.loadgraph", graph);

Page 38: Effiziente persistierung

Entit

yGra

ph• Advantages

• Query specific EAGER loading

• Definition of the graph is independent of the query

• Dynamic creation at runtime

• Disadvantages

• Creates cartesian productwww.thoughts-on-java.org

Page 39: Effiziente persistierung

Caching

www.thoughts-on-java.org

Page 40: Effiziente persistierung

Query Cache

Cach

es

www.thoughts-on-java.org

DB

2nd Level Cache

1st Level Cache

Hibernate Session

1st Level Cache

Hibernate Session

Page 41: Effiziente persistierung

1st Level Cache

www.thoughts-on-java.org

Page 42: Effiziente persistierung

1st L

evel

Cac

he • Activated by default

• Linked to the Hibernate session

• Stores all entities that were used within a session

• Transparent usage

www.thoughts-on-java.org

Page 43: Effiziente persistierung

2nd Level Cache

www.thoughts-on-java.org

Page 44: Effiziente persistierung

2nd L

evel

Cac

he • Session independent entity store

• Needs to be activated• persistence.xml or EntityManagerFactory

• Transparent usage

• PersistenceProvider doesn‘t need to provide it• Not always portable

www.thoughts-on-java.org

Page 45: Effiziente persistierung

2nd L

evel

Cac

he • Shared Cache Mode

• ALL cache all entities

• NONE cache no entities

• ENABLE_SELECTIVE cache needs to be activated for specific entities

• DISABLE_SELECTIVE cache can be deactivated for specific entities

• UNSPECIFIED use default settings of the PersistenceProvider

www.thoughts-on-java.org

Page 46: Effiziente persistierung

2nd L

evel

Cac

he • Cache configuration

• Cache Retrieve Mode

• How to read entities from the cache

• Cache Store Mode

• How to write entities to the cache

• Concurrency Strategy

• How to handle concurrent accesswww.thoughts-on-java.org

Page 47: Effiziente persistierung

Query Cache

www.thoughts-on-java.org

Page 48: Effiziente persistierung

Quer

y Ca

che • Hibernate specific

• Stores query result session independent

• Needs to be activated (persistence.xml)• hibernate.cache.use_query_cache = true

• Activate caching for a specific query• org.hibernate.Query.setCacheable(true)• @NamedQuery(… hints =

@QueryHint(name="org.hibernate.cacheable", value="true"))

www.thoughts-on-java.org

Page 49: Effiziente persistierung

Quer

y Ca

che • Stores query results for a query and its parameters

• [„FROM Author WHERE id=?“, 1] [1]

• Stores only entity references or scalars

• Always use together with 2nd Level Cache

www.thoughts-on-java.org

Page 50: Effiziente persistierung

Reco

mm

enda

tion

s• Only cache data that is seldom updated

• Always benchmark the application when adding or changing caching

• Use Query Cache together with 2nd Level Cache

• Configuration has to fit to each other

www.thoughts-on-java.org

Page 51: Effiziente persistierung

Resources

www.thoughts-on-java.org

Page 52: Effiziente persistierung

Reso

urce

s • JSR 338: JavaTM Persistence API, Version 2.1 http://download.oracle.com/otndocs/jcp/persistence-2_1-fr-eval-spec/index.html

• Hibernate Reference Documentation http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/

• Hibernate Developer Guide http://docs.jboss.org/hibernate/orm/4.3/devguide/en-US/html/

• Hibernate ORM: Tips, Tricks and Performance Techniques by Brett Meyer http://de.slideshare.net/brmeyer/hibernate-orm-performance-31550150

www.thoughts-on-java.org

Page 53: Effiziente persistierung

Reso

urce

s • Java Persistence with Hibernate Second Edition by Christian Bauer, Gaving King, Gary Gregory

• Java Platform, Enterprise Edition: The Java EE Tutorial https://docs.oracle.com/javaee/7/tutorial/index.html

• Hibernate: Truly Understanding the Second-Level and Query Caches http://www.javalobby.org/java/forums/t48846.html

www.thoughts-on-java.org

Page 54: Effiziente persistierung

Slides & Cheat Sheet

www.thoughts-on-java.org

Page 55: Effiziente persistierung

Slid

es &

Che

at

Shee

tGet this presentation and a handy cheat sheet with all the discussed performance tuning tips at

http://www.thoughts-on-java.org/hpt-jug-saxony/

www.thoughts-on-java.org