2009-08-25 4 views
13

Ho un oggetto dominio Hibernate che viene caricato da diverse parti dell'applicazione. A volte è vantaggioso caricare pigro ogni associazione e altri è meglio caricare l'intera cosa in un join. Come compromesso speranzosamente felice che ho trovato:Hibernate: batch_size? Cache di secondo livello?

Utilizzando il recupero in batch, Hibernate può caricare diversi proxy non inizializzati se si accede a un proxy. Il recupero in serie è un'ottimizzazione della strategia di recupero lazy select.

hibernate.default_batch_fetch_size:

Utilizzando recupero batch, Sospensione possibile caricare diversi proxy inizializzate se si delega si accede. Il recupero in serie è un'ottimizzazione della strategia di recupero lazy select .

Vedo anche:

hibernate.jdbc.fetch_size:

Un valore diverso da zero determina la JDBC dimensioni di raccolta (chiamate Statement.setFetchSize()).

Bene Hibernate è abbastanza intelligente da cercare nella cache di secondo livello quando si esegue il recupero in batch? Esegui un recupero per la chiamata iniziale all'associazione e quindi le successive chiamate X colpiscono la cache? In questo modo posso avere il carico pigro che desidero, ma colpisco anche la cache spesso per le transazioni più di massa.

Se l'intero contenuto della raccolta è già contenuto nella cache, eseguirà comunque le query di recupero all'accesso della raccolta?

Grazie.

+0

Ora questo è qualcosa che mi piacerebbe conoscere anche la risposta. – Zoidberg

+1

Segna la mia domanda :-) – davidemm

risposta

6

Ho fatto molte ricerche oggi e sono riuscito a trovare una risposta alla mia domanda. Stavo guardando il codice di Hibernate e il flusso si presenta così:

La raccolta è stata inizializzata?

  • No? Effettua un recupero in batch (gli elementi ottenuti dal batch-fetch vengono inseriti nella cache)
  • Sì? Cerca nella cache per l'oggetto in particolare, se non è presente fai un batch-fetch.

Quindi, se l'elemento nella raccolta che stai cercando è TROVATO nella cache, allora il batch-fetch non avviene. Se l'elemento NON viene trovato nella cache di secondo livello, allora si verifica il recupero in batch, ma eseguirà un recupero di articoli batch indipendentemente dal fatto che gli elementi in batch siano nella cache.


----- ----- ESEMPIO 1

The Good:

(Tre elementi di una collezione - dimensione del lotto di 3) Il primo go:

  • collection.getItem (0) - Nessuna cache | batch-fetch 3 articoli
  • collezione
  • .getItem (1) - caricato per lotti-fetch
  • collection.getItem (2) - caricato in lotti da-fetch

Ora, da qualche altra parte, più avanti nel tempo:

  • raccolta. getItem (0) - cache Hit
  • collection.getItem (1) - cache Hit
  • collection.getItem (2) - cache Hit

----- ESEMPIO 2 -----

Il cattivo:

(Tre elementi in una raccolta - dimensione del lotto di 3)

In questo caso, l'elemento di indice 0 era rimosso dalla cache perché forse la cache era piena e l'elemento è stato eliminato, oppure l'elemento è diventato obsoleto o inattivo.

  • collection.getItem (0) - Non in cache in modo da lotto di 3 (selezionare * dove id in (,,)???)
  • collection.getItem (1) - In Cache Already (sostituito per lotto-fetch comunque)
  • collection.getItem (2) - In cache Already (sostituito da lotto-fetch in ogni caso)

Così il compromesso qui è che avrete un minor numero di chiamate SQL a causa del batch, ma ti mancherai più spesso nella cache. C'è un ticket aperto per avere l'aspetto del batch nella cache di secondo livello prima che entri nel database.

http://opensource.atlassian.com/projects/hibernate/browse/HHH-1775

Votate it up!