Czy istnieją jakieś praktyczne wskazówki lub reguły określające, kiedy przechowywać wartości zagregowane, a kiedy obliczać je w locie?
Załóżmy na przykład, że mam widżety, które użytkownicy mogą oceniać (patrz schemat poniżej). Za każdym razem, gdy wyświetlam widżet, mogłem obliczyć średnią ocenę użytkowników z Ratings
tabeli. Alternatywnie mógłbym zapisać średnią ocenę na Widget
stole. Pozwoliłoby mi to uniknąć konieczności obliczania oceny za każdym razem, gdy wyświetlam widżet, ale musiałbym ponownie obliczać średnią ocenę za każdym razem, gdy użytkownik ocenia widżet.
Ratings Widgets
--------- -------
widget_id widget_id
user_id name
rating avg_rating <--- The column in question
Jak często trzeba obliczać / wyświetlać wartości w stosunku do tego, jak często liczby bazowe są zmieniane / aktualizowane.
Jeśli więc masz witrynę z 10 000 odwiedzin dziennie, która wyświetla wartość, która będzie się zmieniać tylko raz na godzinę, obliczę ją, gdy zmienią się wartości bazowe (może to być wyzwalacz bazy danych, cokolwiek).
Jeśli masz narzędzie do przeglądania statystyk, gdzie statystyki zmieniają się z każdą sekundą, ale tylko trzy osoby mają dostęp i patrzą na to tylko kilka razy dziennie, bardziej prawdopodobne jest, że obliczę w locie. (chyba że zajmuje to kilka minut, aby obliczyć, że posiadanie nieaktualnych danych w pierwszej kolejności nie jest wielkim problemem ... a mój szef mówi mi, żebym generował coś z crona co godzinę, więc nie ma czekać, kiedy będzie chciał na to spojrzeć.)
źródło
Użyj tabeli StaleWidgets jako kolejki „niepoprawnych” (do przeliczenia) widżetów. Użyj innego zadania wątkowego (asynchronicznego), które może przeliczyć te wartości. Okres lub moment ponownych obliczeń zależy od wymagań systemowych:
źródło
Sugerowałbym obliczanie w locie, jeśli obliczanie nie jest zbyt uciążliwe, a jeśli masz złożoną kalkulację i częstą aktualizację, ale nie odczytujesz frequnet niż możesz przechowywać obliczone dane i masz dodatkową kolumnę (bool), która będzie przechowywać, czy ponowne obliczenie jest wymagane, czy nie . np. ustaw tę kolumnę na wartość true za każdym razem, gdy należy wykonać ponowne obliczenie, ale nie wykonuj ponownego obliczania, a gdy wykonujesz ponowne obliczanie, ustaw tę kolumnę jako fałsz (będzie to oznaczać, że obliczona wartość jest najnowsza i nie jest nieaktualna).
W ten sposób nie będziesz musiał ponownie obliczać za każdym razem, będziesz obliczać tylko wtedy, gdy będziesz musiał odczytać, a ponowne przeliczenie wartości kolumny jest prawdziwe. W ten sposób zaoszczędzisz wiele przeliczeń.
źródło
W szczególności w przypadku przypadku istnieje inne rozwiązanie, w którym nie trzeba dodawać wszystkich ocen i dzielić go przez sumę, aby znaleźć średnią. Zamiast tego możesz mieć inne pole, które zawiera sumę recenzji, dlatego za każdym razem, gdy dodajesz ocenę, obliczasz nową średnią za pomocą (avg_rating × total + new_rating) / total, jest to znacznie szybsze niż agregowanie i zmniejsza odczyty dysku, ponieważ nie muszą mieć dostępu do wszystkich wartości oceny. Podobne rozwiązania mogą mieć zastosowanie w innych przypadkach.
Minusem tego jest to, że nie jest to transakcja typu acid, więc możesz zakończyć z nieaktualną oceną. Ale nadal możesz to rozwiązać za pomocą wyzwalaczy w bazie danych. Innym problemem jest to, że baza danych nie jest już znormalizowana, ale nie bój się denormalizować danych w zamian za wydajność.
źródło