Jak estymuje się przestrzeń dyskową dla bazy danych? Dla uproszczenia załóżmy że mam jedną tabelę z dwiema kolumnami, pierwsza typu varchar(20), druga boolean. Ktoś, coś?
To tak nie działa. Oczywiście PI razy drzwi coś można oszacować ale dokładnie to trzeba poznać format w jakim baza zapisuje, wielkość indeksów oraz co to za rodzaj pola char bo char może być jedno bajtowy a może być 4 i więcej bajtowy ( UTF-16, UTF-32 ... )
Ok, w takim razie załóżmy że baza to mysql, innoDb, char to utf8. Skąd wziac wielkość indeksów?
mazurro napisał(a):
Ok, w takim razie załóżmy że baza to mysql, innoDb, char to utf8. Skąd wziac wielkość indeksów?
Trzeba wiedzieć ile jest tych indeksów i jakie mają pola. Jak nie od autorów systemu to nie wiem od kogo ;-)
Powinieneś wziąć pod uwagę następujące aspekty:
- Dane
- Indeksy
- Backupy - jak często, jakiego rodzaju, jak długo przechowywać
- Logi transakcyjne
- Przyrost danych
- BLOBy/CLOBy :-)
- Czy estymujesz netto, czy brutto (tj. czy estymata jest aplikacyjna czy np. uwzględnia też przestrzeń na redundancje - różne RAIDy)
Prosta formułka per tabelka:
sizeof( varchar2(20) + sizeof(boolean) + engine overhead ) * #rows * (1+growthRate)
growthRate
to Twój przyrost danych.
engine overhead
- tyle dodatkowo per wiersz zapisuje silnik bazodanowy, żeby wiersz zapisać
edycja:
Akurat robię specyfikacje interfejsów wymiany danych i wiem ile tych danych będzie i jakiego mniej więcej kształtu, tzn. mam tabelkę z polami:
VARCHAR2(30)
VARCHAR2(3)
VARCHAR2(40)
VARCHAR2(40)
NUMBER
NUMBER
VARCHAR2(30)
VARCHAR2(30)
VARCHAR2(20)
VARCHAR2(50)
VARCHAR2(40)
NUMBER
NUMBER
NUMBER
NUMBER
Wiem, że na wejściu tej tabelki będę miał 800M rekordów, więc moja estymata na storage dla tej tabelki wygląda:
- 9*50 znaków (bo mam 9 pól VARCHAR2 i nie chce mi się rozdrabniać na bajty, wszak to estymata, które z założenia obarczona jest jakimś błędem)
- 6*8 bajtów na NUMBER (co prawda nie będę miał 64bitowych wartości (bo część NUMBER to wartości słownikowe, więc raczej 1,2,3 etc.) - w każdym razie 64 bity na liczbę to całkiem sporo
- semantyka dla VARCHAR2 na bazie to CHAR, a nie BYTE, a że bazę mam w utf32, to mnożę przez 4 bajty (znów pewna nadwyżka, bo nie każdy znak będzie na 4 bajtach)
9x50x4 + 6x8 = > 1800+48 ~ 2kb per wiersz
800M x 2kb => ~1.5 TB
W tych kalkulacjach:
- pominąłem zupełnie narzut na bazę , ale zakładam, że zaokrąglenia w górę na typie danych rozwiąże mi ten problem z nawiązką
- pominąłem growthRate, bo dane będę używał w trybie read only, więc nie będzie przyrostu
W estymacie mam raczej pesymistyczne podejście, ale wolę mieć więcej storage niż mniej :)
Opcje są przynajmniej 3:
1) oszacować rozmiar, aczkolwiek będzie to wartość przybliżona
2) poszukać w dokumentacji i zrozumieć, jak działa zapis danych na dysku przez bazę, przy czym jest to naprawdę trudne zadanie. Kilka dni temu w tym wątku - https://4programmers.net/Forum/1654036 @yarel trochę wyjaśnił, jak wygląda wewnętrzny zapis danych w bazie. Już na pierwszy rzut oka widać, że temat łatwy nie jest. Ponadto każdy silnik, a nawet każda wersja tego samego silnika, może to robić inaczej, w MySQL masz m.in. InnoDB
i MyISAM
i każde z nich podejrzewam, że inaczej sobie radzi z zapisem. Ponadto jeszcze konfiguracja samej bazy, fakt istnienia indeksów itp. też może mieć wpływ na rozmiar bazy
3) Zrób eksperyment - odpal u siebie jakąś bazę, wrzuć 1000, 200000, 5000000 i 200000000 rekordów, zmierz rozmiar i wyciągnij wnioski.
Osobiście polecam podejście numer 3 - eksperymenty zawsze są rozwojowe i nawet jeśli wyniki nie będą przydatne, to i tak czegoś się nauczysz i nabierzesz trochę wprawy. Tylko jeszcze jedna uwaga - pamiętaj, że nie zawsze elementy usunięte są od razu fizycznie kasowane z dysku. Czasami są jedynie oznaczane jako skasowane (coś jakbyś w książce jedynie wykreślił pozycję ze spisu treści, ale fizycznie kartek nie wyrwał), dlatego dobrze jest upewnić się, że co pewien czas na bazie jest puszczany VACUUM
. Inaczej Twoje obliczenia będą bardzo nietrafne - bo indeksów "aktywnych" będzie niewiele, ale baza na dysku będzie dość potężna.
Super, dzięki za odpowiedzi. Bardzo pomocne.
Wziąć wszystkie powyższe metody i najwyższy wynik pomnożyć x 3. Powinno być ok:)
cerrato napisał(a):
Opcje są przynajmniej 3:
1) oszacować rozmiar, aczkolwiek będzie to wartość przybliżona
2) poszukać w dokumentacji i zrozumieć, jak działa zapis danych na dysku przez bazę, przy czym jest to naprawdę trudne zadanie. Kilka dni temu w tym wątku - https://4programmers.net/Forum/1654036 @yarel trochę wyjaśnił, jak wygląda wewnętrzny zapis danych w bazie. Już na pierwszy rzut oka widać, że temat łatwy nie jest. Ponadto każdy silnik, a nawet każda wersja tego samego silnika, może to robić inaczej, w MySQL masz m.in.InnoDB
iMyISAM
i każde z nich podejrzewam, że inaczej sobie radzi z zapisem. Ponadto jeszcze konfiguracja samej bazy, fakt istnienia indeksów itp. też może mieć wpływ na rozmiar bazy
3) Zrób eksperyment - odpal u siebie jakąś bazę, wrzuć 1000, 200000, 5000000 i 200000000 rekordów, zmierz rozmiar i wyciągnij wnioski.Osobiście polecam podejście numer 3 - eksperymenty zawsze są rozwojowe i nawet jeśli wyniki nie będą przydatne, to i tak czegoś się nauczysz i nabierzesz trochę wprawy. Tylko jeszcze jedna uwaga - pamiętaj, że nie zawsze elementy usunięte są od razu fizycznie kasowane z dysku. Czasami są jedynie oznaczane jako skasowane (coś jakbyś w książce jedynie wykreślił pozycję ze spisu treści, ale fizycznie kartek nie wyrwał), dlatego dobrze jest upewnić się, że co pewien czas na bazie jest puszczany
VACUUM
. Inaczej Twoje obliczenia będą bardzo nietrafne - bo indeksów "aktywnych" będzie niewiele, ale baza na dysku będzie dość potężna.
Do tego jeszcze dochodzi defragmentacja - czyli baza może zawierać dwa raz więcej niż same dane. Pytanie też jak duże będziesz robił transakcje i ile miejsca potrzebujesz na jakieś tempy itp. Jeśli chodzi o podejście akademickie to możesz to jakoś policzyć, jeśli chodzi o życie, to pomnóż to co ci wyjdzie razy 10 i może się zmieści.