2009-05-07 18 views
5

Szukam zaprojektować bazę danych dla strony internetowej, na której użytkownicy będą mogli zdobywać punkty (reputację) za wykonywanie niektórych czynności i zmagam się z projektem bazy danych.Jaki jest najlepszy sposób przechowywania/obliczania wyników użytkowników?

Mam zamiar przechowywać zapisy rzeczy, które robi użytkownik, aby mieć 25 punktów za nadesłany przedmiot, 1 punkt za 30 komentarzy, które zrobili, i kolejne 10 punktów za bycie niesamowitym!

Oczywiście wszystkie dane będą tam dostępne, ale wygląda na to, że dużo lub zapytano o łączny wynik dla każdego użytkownika, który chciałbym wyświetlić obok jego nazwy użytkownika (w postaci poziomu). Na przykład zapytanie do tabeli elementów przesłanych, aby uzyskać wyniki dla każdego elementu od tego użytkownika, zapytanie do tabeli komentarzy itp. Jeśli wszystko to musi zostać wykonane dla każdego użytkownika wymienionego na stronie ... DUŻO zapytań !

Zastanawiałem się nad utrzymywaniem wyniku w tabeli użytkownika, co wydaje się o wiele szybszym sprawdzeniem, ale miałem już do czynienia z tym, że przechowywanie danych, które można obliczyć z innych danych, to ZŁY!

Widziałem wiele stron, które robią podobne rzeczy (nawet przepełnienie stosu jest podobne), więc uważam, że musi istnieć "najlepsza praktyka" do naśladowania. Czy ktoś może zasugerować, co to może być?

Wszelkie sugestie lub komentarze będą świetne. Dzięki!

Odpowiedz

3

Myślę, że to zdecydowanie świetne pytanie. Musiałem zbudować systemy, które mają podobne zachowanie do tego - szczególnie, gdy tabela z wynikami w niej jest dostępna dość często (jak w twoim scenariuszu).Oto moja propozycja dla Ciebie:

Najpierw należy utworzyć kilka tabel jak następujące (używam programu SQL Server najlepszych praktyk, ale nazwać je jednak zobaczyć fit):

UserAccount   UserAchievement 
-Guid (PK)   -Guid (PK) 
-FirstName   -UserAccountGuid (FK) 
-LastName   -Name 
-EmailAddress  -Score 

Po wykonaniu tego śmiało i utworzyć widok, który wygląda mniej więcej tak (nie, ja nie zweryfikował SQL, ale powinien być dobry start):

SELECT [UserAccount].[FirstName]  AS FirstName, 
     [UserAccount].[LastName]  AS LastName, 
     SUM([UserAchievement].[Score]) AS TotalPoints 
FROM [UserAccount] 
INNER JOIN [UserAchievement] 
    ON [UserAccount].[Guid] = [UserAchievement].[UserAccountGuid] 
GROUP BY [UserAccount].[FirstName], 
     [UserAccount].[LastName] 
ORDER BY [UserAccount].[LastName] ASC 

wiem już wspomniano pewne obawy o wydajności i wiele pytań, ale jeśli zbudujesz taki widok, nigdy nie będziesz potrzebował m Rudy niż jeden. Nie polecam robić tego zmaterializowanego widoku; zamiast tego wystarczy zindeksować tabele, aby potrzebne wyszukiwania (zasadniczo UserAccountGuid) umożliwiły szybkie sumowanie w tabeli.

Dodam jeszcze jeden punkt - jeśli twoja tabela UserAccount stanie się ogromna, możesz rozważyć nieco bardziej inteligentne zapytanie, które zawierałoby nazwy kont, których potrzebujesz do roll-upów. Umożliwi to nie zwracanie ogromnych zestawów danych do Twojej strony internetowej, gdy wyświetlasz tylko 3-10 informacji o użytkownikach na stronie. Musiałbym pomyśleć nieco więcej o tym, jak to zrobić elegancko, ale proponuję trzymać się z dala od instrukcji "IN", ponieważ spowoduje to liniowe przeszukiwanie tabeli.

1

Dla bardzo wysokich współczynników odczytu/zapisu, denormalizacja jest bardzo ważną opcją. Możesz skorzystać z widoku indeksowanego, a dane będą przechowywane w sposób zsynchronizowany (więc nigdy nie musisz się martwić, że dane o błędach są złe). Wadą jest to, że jest on zsynchronizowany .. tak więc aktualizacje sumy sklepu są synchronicznym aspektem zatwierdzania akcji punktowej. Zwykle byłoby to dość szybkie, ale jest to decyzja projektowa. Jeśli dokonasz denormalizacji, możesz wybrać, czy chcesz mieć jakiś opóźniony system aktualizacji.

Osobiście chciałbym przejść z indeksowanym widokiem do rozpoczęcia, a następnie można go dość płynnie zastąpić konkretnym stołem, jeśli dyktuje to twoje potrzeby.

+0

Przepraszam, jestem głupia - nie zauważyłem aspektu mysql. Nie sądzę, aby jeszcze indeksowały wyświetlenia. Normalną alternatywą, aby wymusić synchronizację, jest ustawienie wyzwalaczy. – ahains

+0

Wyzwalacze sprawiają, że dziecko Jezus płacze. Cóż, i tak mnie to płacze. Nawet jeśli nie jest on zindeksowany, widok jest twoim przyjacielem. – Adrien

0

W przeszłości zawsze używaliśmy pewnego rodzaju nocnych lub peryferycznych zadań cron do obliczania bieżącego wyniku i zapisywania go w bazie danych - coś w rodzaju trwałego widoku SUM na tabeli działań. Podobnie jak w przypadku większości "najlepszych praktyk", są one po prostu wytycznymi, a często lepiej i bardziej praktycznie odejść od konkretnej praktyki na ściśle określonych obszarach.

Co więcej, to nie jest tak naprawdę duże odchylenie, jeśli używasz zadania cron, ponieważ jest lepiej postrzegane jako pamięć podręczna przechowywana w bazie danych.

0

Jeśli masz oddzielną tabelę wyników, możesz ją zaktualizować za każdym razem, gdy element zostanie przesłany lub komentarz zostanie opublikowany przez użytkownika. Możesz to zrobić za pomocą wyzwalacza lub kodu witryny.

Wyniki użytkowników będą aktualizowane w sposób ciągły i mogą być szybko wyszukiwane w celu wyświetlenia.

Powiązane problemy