2010-01-04 11 views
9

In relazione a questa questionHibernate query cache - per oggetti non nella cache di 2 ° livello - rischioso? utile? cattive pratiche?

Premessa:

Queste sono le mie assunzioni, basate sulla mia lettura, esperienza e comprensione, si può essere sbagliato, se lo sono, si prega di commento e Io modificare la domanda .

  • cache delle query è un bene per lo più lungo con cache di 2 ° livello
  • cache delle query memorizza nella cache i risultati delle query identificatori + parametri
  • cache di query è rischioso se il database è stato cambiato, e non si è riflesso al cache di

domanda:

ho un oggetto che non si trova nella cache di 2 ° livello. A causa di una programmazione errata o di altri vincoli, il codice che carica l'oggetto viene chiamato più volte nella stessa sessione di sospensione. Il retrival utilizza una query di ricerca HQL ad es.

hibernateTemplate.find("from Foo f where f.bar > ?", bar); 

Prima di aggiungere cache delle query, se il codice di cui sopra è stato chiamato N volte all'interno della stessa sessione Hibernate, c'erano N colpisce al database

Poi ho voluto vedere cosa succede se aggiungo cache delle query:

Query query = session.createQuery("from Foo f where f.bar > ?"); 
query.setCacheable(true); 
query.setParameter(bar); 
query.list(); 

Quando ho aggiunto cache delle query, ho notato che durante la stessa sessione, Hibernate non ha colpito i tempi di database N più, solo una volta per sessione.

  1. Quindi la mia prima ipotesi è che Hibernate prima effettui ricerche nella Session Cache, quindi nella 2 ° Cache di livello. Questa supposizione è corretta?
  2. Suppongo anche che se l'oggetto() che non si trova nella cache di secondo livello, sia stato modificato nel database, la cache di query, in ambito incrociato, restituirà gli identificatori errati e quindi gli oggetti errati. È corretto?
  3. È quindi sicuro dire che l'utilizzo della cache di query per le query che includono informazioni immutabili anche per gli oggetti cache non 2L è una buona pratica? (Ad esempio una query che la sua clausola WHERE contiene una condizione che sarà sempre tornare gli stessi risultati, ad esempio, "selezionare p.ser_num dove p.id =?", Quando SER_NUM e id coppie non cambiano una volta creato)

By il modo in cui, nel relativo documento question, si afferma che la cache delle query non funziona sull'ambito della Session Cache. Sono in grado di capire che affermazione o qualcos'altro?

+3

+1 per una domanda formata, formattata e ricercata in modo eccellente. –

risposta

5

La cache query è un particolare tipo di cache di 2 ° livello . Quello che tu definisci cache di secondo livello preferirei chiamare "object cache".

commenti sul tuo ipotesi:

  • cache delle query è buono per lo più lungo con cache di 2 ° livello (aka oggetto cache).

Una cache delle query tiene solo i risultati delle prime query come chiavi primarie, in ibernazione dire, id. Non tiene gli oggetti idratati reali. Questo ha senso quando esegui una query con jdbc solo in realtà ti restituisce gli oggetti idratati (popolati) mentre esegui l'iterazione sul ResultSet. L'affermazione non è necessariamente corretta. Se la query è molto complicata e richiede così molto tempo per essere eseguita, utilizzando una cache di query si risparmia tale tempo. Non sarà possibile, utilizzando una cache di query, salvare il tempo necessario per caricare gli oggetti dal database.

  • cache delle query è rischioso se il database è stato cambiato, e non si è riflesso alla cache

Questo è vero, ma non è unica per interrogare la cache , lo stesso vale per ciò che si definisce cache di secondo livello, ma ciò che viene in genere chiamato cache degli oggetti.

Così la mia prima ipotesi è che Hibernate prime ricerche nel sessione Cache, poi nel 2 ° livello cache. Questa supposizione è corretta?

Sì, quando si caricano oggetti questo è il comportamento.

Suppongo inoltre che se l'oggetto (Foo) , che non si trova nella cache di 2 ° livello, è stato cambiato nel database, quindi cache delle query, essendo sessione croce ambito, restituirà il torto identificatori e quindi gli oggetti errati . È corretto?

Sì, saranno interessati sia la cache degli oggetti che la cache delle query. Questo è motivo di preoccupazione se il database viene modificato senza passare attraverso l'ibernazione. È possibile mitigare potenzialmente l'effetto impostando il timeout della cache della query.

E 'quindi giusto dire che l'utilizzo della cache query per le query che includono informazioni immutabile anche per 2L oggetti non memorizzati nella cache, è una buona pratica? (ad esempio una query che la sua clausola WHERE contiene una condizione che sarà sempre restituire gli stessi risultati, ad esempio, "selezionare p.ser_num dove p.id =?", Quando SER_NUM e id coppie non cambiano una volta creato)

Per questo tipo di oggetti non c'è motivo di non utilizzare sia una cache di oggetti che una cache di query.

E sì, cache delle query non funziona a livello di sessione aka Livello 1 cache. Quindi, il motivo per cui quando si esegue nuovamente la query, si verifica nuovamente il database. Non inserirà il risultato (set ID) di una query nella cache di sessione.

+0

Grazie per la risposta molto approfondita, una cosa che non capisco. quando hai scritto "Non inserirà il risultato (set ID) di una query nella cache della sessione." - quando "colpisce di nuovo il database" esegue la query così com'è? o semplicemente carica gli oggetti per ID in una query "seleziona in"? Quando l'ambito della sessione è terminato, la cache delle query deve ancora contenere gli ID anche se si tratta di un oggetto non nella cache di secondo livello, giusto? –

+0

Se la query non è una query memorizzata nella cache, colpirà il database ogni volta (la query completa), come hai visto. Se è configurato per la cache, colpirà il database per la prima volta e non di nuovo. Quello che ti suggerisco di fare è attivare la registrazione sql tramite il parametro di ibernazione o impostare org.hibernate.SQL su DEBUG in modo da poter vedere esattamente quando sta colpendo il database. –

2

solo supposizioni:

Secondo questa article da Hibernate documentazione:

[cache delle query] crea due nuove regioni della cache : uno in possesso di cache di query Set di risultati (org .hibernate.cache.StandardQueryCache), gli altri timestamp di attesa degli aggiornamenti più recenti da interrogare tabelle (org.hibernate.cache.UpdateTimestampsCache).

Presumo che ciò significa che ogni volta che il timestamp della tabella queryable è più recente il risultato-set - causerà ibernazione di avvicinarsi al DB nel il prossimo invito a tale query, e che ciò che mantengono la cache delle query sicuro in qualche aspetto.

Ma 2 frasi più avanti nello stesso paragrafo della documentazione che dice:

La cache delle query deve essere sempre utilizzato in combinazione con il secondo livello cache.

ancora una volta, la mia ipotesi è che questo è l'unico ibernazione modo può essere a conoscenza di modifiche al database che sono fatto per sessione di questo utente specifico

+0

+1 molto buona risposta –

1

Per la domanda n. 3, non penso che vogliate utilizzare la cache di query quando gli oggetti non sono memorizzati nella cache. Finirai con tutti gli id ​​principali ma dovrai colpire il database una volta per chiave per recuperare gli oggetti che potrebbero essere più lenti rispetto all'esecuzione della query senza alcuna memorizzazione nella cache. A partire dal 3.3, forse nelle versioni più recenti prende gli oggetti mancanti usando meno query, ad es. dove id in (: id1,: id2, ...).

Problemi correlati