2010-01-04 18 views
9

Podobne do tego questionPamięć podręczna zapytania w poszukiwaniu hibernacji - dla obiektów spoza pamięci podręcznej drugiego poziomu - ryzykowne? przydatny? zła praktyka?

Pomieszczenie:

To są moje założenia, w oparciu o moje doświadczenia, czytania i rozumienia, mogą być źle, jeśli są, proszę o komentarz i będę edytować pytanie .

  • cache zapytań jest dobre w większości wraz z cache 2. poziom
  • cache zapytań buforuje wyniki identyfikatory zapytań + parametrach
  • cache zapytań jest ryzykowne, jeśli baza danych została zmieniona, i nie zostało odzwierciedlone do cache

Pytanie:

mam obiekt, który nie jest w pamięci podręcznej poziomu 2. Z powodu złego programowania lub innych ograniczeń, kod ładujący obiekt jest wywoływany kilka razy w tej samej sesji hibernacji. Odzyskiwanie wykorzystuje zapytanie HQL find np.

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

Przed dodaniem cache zapytań, jeśli powyższy kod został nazwany N razy w tym samym hibernacji sesji było N trafia do bazy danych

Potem chciałem zobaczyć, co się stanie, jeśli dodam cache zapytań:

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

Kiedy dodałem cache zapytań, zauważyłem, że podczas tej samej sesji, Hibernate nie trafić na bazie N razy więcej, tylko raz na sesję.

  1. Moje pierwsze założenie jest takie, że Hibernate najpierw wyszukuje w pamięci podręcznej sesji, a następnie w buforze drugiego poziomu. Czy to założenie jest poprawne?
  2. Zakładam również, że jeśli obiekt (Foo), który nie znajduje się w pamięci podręcznej drugiego poziomu, został zmieniony w bazie danych, a następnie bufor zapytań, z uwzględnieniem zakresu sesji, zwróci nieprawidłowe identyfikatory, a tym samym nieprawidłowe obiekty. Czy to jest poprawne?
  3. Czy można bezpiecznie powiedzieć, że używanie pamięci podręcznej zapytań dla zapytań zawierających niezmienną informację nawet dla obiektów z pamięciami buforowymi innych niż 2L jest dobrą praktyką? (np. zapytanie, że klauzula where zawiera warunek, który zawsze zwróci te same wyniki, np. "wybierz p.ser_num, gdzie p.id =?" gdy pary ser_num i id nie zmieniają się po utworzeniu)

Autor sposób, w pokrewnym question twierdzi się, że pamięć podręczna zapytań nie działa w zakresie pamięci podręcznej sesji. Czy nie rozumiem tego twierdzenia, czy cokolwiek innego?

+3

+1 za doskonale uformowane, sformatowane i zbadane pytanie. –

Odpowiedz

5

cache zapytań jest szczególnym rodzajem pamięci podręcznej 2 poziomie . To, co określasz jako pamięć podręczna drugiego poziomu, wolałbym nazywać "pamięć podręczną obiektów".

Uwagi na temat swoich założeniach:

  • cache zapytanie jest dobry głównie wraz z pamięci podręcznej poziomu 2 (aka sprzeciw cache).

cache zapytań posiada tylko surowe wyniki zapytań jak kluczy podstawowych, w hibernacji mówić, id użytkownika. Nie zawiera rzeczywistych uwodnionych obiektów. Ma to sens, ponieważ po uruchomieniu zapytania z jdbc w rzeczywistości tylko oddaje nawodnione (wypełnione) obiekty podczas iteracji po zestawie wynikowym. Oświadczenie niekoniecznie jest poprawne. Jeśli zapytanie jest bardzo skomplikowane i trwa bardzo długo, to dzięki pamięci podręcznej zapytań zaoszczędzisz ten czas. Nie użyjesz pamięci podręcznej zapytań, oszczędź czasu potrzebnego na załadowanie obiektów z bazy danych.

  • cache zapytań jest ryzykowne, jeśli baza danych została zmieniona, i nie zostało odzwierciedlone do pamięci podręcznej

To prawda, ale to nie jest unikalny dla zapytania cache To samo dotyczy tego, co nazywamy pamięcią podręczną drugiego poziomu, ale co zwykle nazywa się pamięcią podręczną obiektów.

Więc moim pierwszym założeniem jest to, że Hibernate Pierwsze wyszukiwania w Session Cache, następnie w 2. Poziom Cache. Czy to założenie jest poprawne?

Tak, podczas ładowania obiektów jest to zachowanie.

ja też założyć, że jeśli obiekt (Foo) który nie znajduje się w pamięci podręcznej 2 poziomie, został zmieniony w bazie danych, a następnie cache zapytań, jest krzyż sesja scoped powróci złą identyfikatory, a tym samym złe obiekty . Czy to jest poprawne?

Tak, dotyczy to zarówno pamięci podręcznej obiektów, jak i pamięci podręcznej zapytań. Jest to niepokojące tylko wtedy, gdy baza danych zostanie zmieniona bez przechodzenia przez hibernację. Możesz potencjalnie złagodzić efekt poprzez ustawienie limitu czasu pamięci podręcznej zapytań.

Czy zatem śmiało powiedzieć, że za pomocą pamięci podręcznej zapytań dla zapytań zawierających niezmienny informacji nawet dla 2L pamięci podręcznej obiektów, jest dobrą praktyką? (np kwerendy że jego gdzie klauzula zawiera warunek, że będzie zawsze zwraca te same rezultaty, na przykład „wybierz p.ser_num gdzie p.id =?”, Gdy ser_num i id pary nie należy zmieniać raz stworzony)

Dla tego rodzaju obiektów nie ma powodu, aby nie używać zarówno pamięci podręcznej obiektów, jak i pamięci podręcznej zapytań.

I tak, pamięć podręczna zapytań nie działa na poziomie sesji, podobnie jak pamięć podręczna poziomu 1. Dlatego powód, dla którego po ponownym uruchomieniu zapytania ponownie trafia do bazy danych. Nie spowoduje to umieszczenia wyniku (ustawienia identyfikatora) zapytania w pamięci podręcznej sesji.

+0

Dziękuję za bardzo dokładną odpowiedź, jedno nie rozumiem. kiedy napisałeś "Nie spowoduje to umieszczenia wyniku (ustawienia identyfikatora) zapytania w pamięci podręcznej sesji." - kiedy "trafi ponownie do bazy danych", wykonuje zapytanie tak jak jest? lub po prostu ładuje obiekty według identyfikatora w kwerendzie "wybierz w"? Gdy zakres sesji się skończy, pamięć podręczna zapytań nadal powinna przechowywać identyfikatory, nawet jeśli są one obiektem nie znajdującym się w pamięci podręcznej drugiego poziomu, prawda? –

+0

Jeśli zapytanie nie jest zapytaniem z pamięci podręcznej, trafi ono do bazy danych za każdym razem (pełne zapytanie). Jeśli jest skonfigurowany do przechowywania w pamięci podręcznej, trafi do bazy danych po raz pierwszy, a nie ponownie. To, co sugeruję, to włączyć rejestrowanie sql przez parametr hibernacji lub ustawienie org.hibernate.SQL na DEBUG, aby można było zobaczyć dokładnie, kiedy trafia do bazy danych. –

2

tylko założenia:

Według tego article z dokumentacją hibernacji:

[cache zapytań] tworzy dwie nowe cache regiony: jeden trzyma w pamięci podręcznej zapytań Zestawy wyników (org .hibernate.cache.StandardQueryCache), pozostałe sygnatury czasowe ostatnich najnowszych aktualizacji do zapytania tabele (org.hibernate.cache.UpdateTimestampsCache).

Zakładam, oznacza to, że gdy datownik tabeli queryable jest nowszy niż wynik-set - spowoduje to hibernacji, aby zbliżyć się do DB w kolejnym wezwaniu do tego zapytania, a co zachować pamięć cache zapytań bezpieczne w pewnym aspekcie.

Ale 2 zdań później w tym samym punkcie dokumentacji jest napisane:

Pamięć podręczna zapytań należy zawsze stosować w połączeniu z drugiego poziomu pamięci podręcznej.

znowu moje założenie, że jest to jedyny sposób hibernacji może być świadomi zmian w bazie danych, które są wykonane z sesji Ten specyficzny użytkownika

+0

+1 bardzo dobra odpowiedź –

1

Dla twojego pytania nr 3, nie sądzę, że chcesz używać pamięci podręcznej zapytań, gdy obiekty nie są buforowane. Otrzymasz wszystkie podstawowe identyfikatory, ale będzie musiał trafić bazę danych raz na klucz, aby pobrać obiekty, które mogą być wolniejsze niż uruchomienie kwerendy bez buforowania w ogóle. Od wersji 3.3 może w nowszych wersjach pobiera brakujące obiekty, używając mniejszej liczby zapytań, np. gdzie id in (: id1,: id2, ...).

Powiązane problemy