Poproszono mnie o stworzenie czegoś, co śledzi dzienny koszt gromadzenia na kontach, i próbuję wymyślić schemat tabeli bazy danych, który by to obsługiwał.
Oto co wiem
- Firma ma ponad 2,5 miliona kont
- Spośród nich obecnie pracują średnio 200 000 miesięcznie (co zmienia się wraz z poziomem zatrudnienia, który jest obecnie niski)
- Mają 13 różnych rodzajów kosztów, które chcieliby śledzić, i ostrzegli, że mogą dodać więcej w przyszłości
- Chcą, aby koszty były śledzone codziennie
- Koszty nie są dzielone na cały asortyment. Są one podzielone na liczbę kont obsługiwanych miesięcznie (200 000) lub użytkownicy mogą wprowadzić identyfikatory kont, aby zastosować koszt do grupy kont, lub mogą po prostu określić, dla których kont zastosować koszt.
Moją pierwszą myślą była znormalizowana baza danych:
ID konta Data CostTypeId Ilość
Moim problemem jest robienie matematyki. Ten stół szybko się powiększy. Zakładając, że wszystkie 13 rodzajów kosztów zostanie zastosowanych do wszystkich obsługiwanych kont w bieżącym miesiącu, czyli 200k * 13 * N days in month
około 75-80 milionów rekordów miesięcznie lub blisko miliarda rekordów rocznie.
Moją drugą myślą było nieco zdenormalizować to
ID konta Data Całkowity koszt CostType1 CostType2 CostType3 CostType4 CostType5 CostType6 CostType7 CostType8 CostType9 CostType10 CostType11 CostType12 CostType13
Ta metoda jest bardziej zdenormalizowana i może tworzyć do 6 milionów rekordów miesięcznie ( 200k * N days in month
) lub około 72 milionów rocznie. Jest to o wiele mniej niż pierwsza metoda, jednak jeśli firma zdecyduje się na nowy typ kosztów w przyszłości, konieczne będzie dodanie kolejnej kolumny bazy danych.
Z dwóch metod, które wolisz? Dlaczego? Czy istnieje inna alternatywa, która mogłaby wymyślić, która poradziłaby sobie z tym lepiej?
Najbardziej interesuje mnie raportowanie wyników, zarówno raportów letnich, jak i szczegółowych. Zadanie, które rozłoży koszty na konta, będzie wykonywane co noc, gdy nikogo nie będzie w pobliżu. Drugim problemem jest rozmiar bazy danych. Istniejąca baza danych ma już prawie 300 GB i uważam, że miejsce na dysku wynosi około 500 GB.
Baza danych to SQL Server 2005
Odpowiedzi:
Miliard rekordów rocznie to niewiele.
Z partycjonowaniem (być może dla każdego rodzaju kosztów) i archiwizacją można zarządzać.
Liczba elementów danych do przechowywania wynosi nadal 200 tys. * 13 * N.Jako kolumny otrzymasz mniej wierszy na stronę i zajmie więcej miejsca niż jako wiersze. Możesz zyskać, jeśli „CostType1” nie jest typem danych o stałej długości, ale jest marginalny.
„KISS” jak mówią
źródło
Chociaż Twój projekt może z pewnością zmienić noc lub dzień, w tym przypadku skupiłbym się bardziej na indeksach, w tym uwzględnieniu indeksów w razie potrzeby. Chciałbym również przyjrzeć się niektórym narzędziom, które udostępnia SQL Server do obsługi bardzo dużych tabel, takich jak partycjonowanie tabel.
Pomyśl o tym w ten sposób, mimo że w tabeli znajduje się 80 miliardów rekordów, z odpowiednim indeksowaniem, te, które naprawdę jesteś zainteresowany w danym momencie, zostaną zgrupowane fizycznie na dysku. Ze względu na sposób organizacji danych w serwerze SQL dane podzielone według granic indeksu mogą również znajdować się w innej tabeli, ponieważ nie musi czytać całej tabeli, aby uzyskać to, czego potrzebuje.
Jeśli zdecydujesz się także podzielić tabelę na partycje, możesz poprawić czas dostępu i czas wstawiania.
źródło
Normalizowałbym się. Przeprowadziliśmy księgowanie kosztów pod kątem rentowności kont klientów w banku i wygenerowaliśmy ponad 250 mln rzędów kosztów indywidualnych, stosując setki sterowników, które zostały przypisane przez centrum kosztów lub księgę główną lub różne inne techniki na milionach kont każdego miesiąca.
Na przykład całkowity koszt obsługi bankomatów został podzielony między konta, które korzystały z bankomatów, na podstawie względnej wielkości wykorzystania. Jeśli więc wydano 1 mln USD na obsługę bankomatów, a tylko 5 klientów skorzystało z niego raz, a jeden klient użył go 5 razy, to ten jeden klient kosztował banku 0,5 mln USD, a pozostali klienci kosztowali banku 1 mln USD każdy. Inne sterowniki mogą być znacznie bardziej złożone.
Ostatecznie prawdopodobnie okaże się, że jest rzadki - niektóre konta nie uzyskują kosztów z niektórych źródeł / sterowników - a niektóre konta nie dostają niczego. W znormalizowanym modelu te wiersze nie istnieją. W modelu zdormalizowanym wiersz istnieje, z pewnymi pustymi kolumnami. Ponadto, w rzadkim znormalizowanym modelu, powinieneś zobaczyć poprawę wydajności, ponieważ istnienie wiersza jest zwykle szybsze do sprawdzenia (z indeksem pokrywającym na CostType) niż sprawdzenie wszystkich wierszy o wartości innej niż NULL w określonym „segmencie” (nawet z indeksy w każdej kolumnie kwoty - co widać, zaczyna się bardzo marnować).
źródło
Niezależnie od korzyści z wydajności zdecydowanie poparłbym wariant 1. Moim zdaniem opcja 2 okradłaby Piotra, by zapłacić Paulowi.
źródło
Wybrałbym opcję 1, a następnie, jeśli prędkość raportowania stałaby się problemem w dalszej części drogi, dodałbym również tabelę 2 i umieściłem ją w bazie danych raportowania w jakimś zautomatyzowanym procesie z dnia na dzień / poza szczytem.
Możesz również rozważyć zebranie dziennej struktury tabeli 2 w dalsze tygodniowe, miesięczne, kwartalne, roczne zestawienia, jeśli jest to uzasadnione.
Ale, jak powiedziałem, zdecydowałbym się również przechowywać „surowe” dane w odpowiedniej (znormalizowanej) formie.
źródło
Biorąc pod uwagę wspomniane woluminy, wybrałbym drugą opcję, ale bez TotalCost. Można powiedzieć, że nadal jest znormalizowany.
Edycja: alternatywnie, w zależności od wymagań i wielkości AccountId, możesz również rozważyć następujące kwestie:
Dzięki takiemu projektowi nadal możesz dodać zdormalizowany TotalCost do pierwszej tabeli i dokonać ponownej kalkulacji w nocy, co pozwoli na uruchomienie niektórych raportów tylko na pierwszej tabeli.
źródło
TotalCost
tam, ponieważ większość raportów jest podsumowana, i pomyślałem, że szybsze byłoby zapytanie o jedną wartość niż dodanie 13 różnych wartości.powinieneś właściwie podzielić tabelę jodły na dwie tabele, abyś mógł użyć podzapytania i wybrać drugi wiersz jako kolumnę lub wiele kolumn. jest w ten sposób bardziej elastyczny i dzięki temu można łatwiej uzyskać wynik podobny do drugiego.
źródło