Tło :
Stworzyłem aplikację internetową, którą chciałbym móc odpowiednio skalować. Wiem, że nie jestem Google ani Twitterem, ale moja aplikacja używa dość dużej ilości danych dla każdego użytkownika, a zatem ma dość wysokie wymagania dotyczące danych. Chcę być gotowy do skalowania w miarę dobrze bez konieczności późniejszej zmiany architektury.
Uważam się za programistę, a nie eksperta od baz danych. Dlatego piszę tutaj. Mam nadzieję, że ktoś z dużo większą wiedzą na temat baz danych może mi doradzić.
Przy względnie dużej liczbie użytkowników, ale nie takich jak numery na Facebooku, oczekuję, że będę mieć DB, która wygląda następująco:
Jeden „duży stół”:
- 250 milionów rekordów
- 20 kolumn
- Około 100 GB danych
- Ma indeksowany klucz obcy bigint (20)
- Ma indeksowaną kolumnę varchar (500) string_id
- Ma kolumnę „wartość” int (11)
4 inne tabele:
- 10 milionów rekordów każdy
- Po około 2–4 GB danych
- każda z tych tabel ma 4–8 kolumn
- jedna kolumna jest datowana data_tworzona
- jedna kolumna jest kolumną varchar (500) string_id
- jedna lub dwie kolumny z każdej z tych tabel zostaną wybrane w złączeniu
Jedna z tych tabel jest używana do przechowywania średnich - jej schemat to bigint (20) id, varchar (20) string_id, data-godzina utworzona, zmiennoprzecinkowa wartość średnia
Co chcę zrobić - dwa stosunkowo drogie zapytania:
Oblicz nowe średnie wartości:
- Używając klucza obcego, wybierz do kilku milionów oddzielnych rekordów z dużej tabeli.
- Oblicz nową średnią, grupując według string_id.
- Wstaw wyniki do tabeli średnich.
- W tej chwili w tej kwerendzie używane są dwa sprzężenia.
Twórz zdenormalizowane rekordy tylko do odczytu do obsługi użytkowników:
- Za pomocą klucza obcego wybierz dowolne miejsce spośród 1000–40 000 rekordów z dużego stołu.
- Połącz z każdą z pozostałych czterech tabel najnowszego rekordu za pomocą kolumny id łańcucha.
- Wstaw wyniki do zdenormalizowanej tabeli.
- Te rekordy są używane przez interfejs użytkownika do wyświetlania informacji użytkownikom.
- W tej chwili w tej kwerendzie używane są cztery sprzężenia.
Planuję uruchomić każde z tych drogich zapytań w bazie danych zaplecza wsadowego, która przekaże wyniki do front-endowego serwera DB w czasie rzeczywistym, który obsługuje żądania od użytkowników. Te zapytania będą uruchamiane w regularnych odstępach czasu. Nie zdecydowałem, jak często. Średnie zapytanie może być wykonane raz dziennie. Zapytanie o znormalizowanie będzie musiało być częstsze - może co kilka minut.
Każde z tych zapytań jest obecnie uruchamiane w MySQL w ciągu kilku sekund na bardzo niskiej jakości komputerze z zestawem danych z 100 000 rekordów w „dużej tabeli”. Martwi mnie zarówno moja zdolność do skalowania, jak i koszty skalowania.
Pytania :
- Czy to podejście wydaje się uzasadnione? Czy jest z tym coś złego z dużej perspektywy?
- Czy RDBMS jest właściwym narzędziem, czy powinienem spojrzeć na inne rozwiązania „big data”, takie jak coś w rodzinie Hadoop? Moją skłonnością jest używanie RDBMS, ponieważ dane są ustrukturyzowane i ładnie pasują do modelu relacyjnego. Jednak w pewnym momencie rozumiem, że mogę już nie być w stanie korzystać z RDBMS. Czy to prawda? Kiedy ten przełącznik będzie potrzebny?
- Czy to zadziała? Czy zapytania te można uruchomić w rozsądnym czasie? Mogę poczekać godziny na zapytanie nr 1, ale zapytanie nr 2 powinno zakończyć się za kilka minut.
- Co powinienem rozważyć z perspektywy sprzętowej? Jakie mogą być wąskie gardła mojej pamięci RAM i procesora? Zakładam, że utrzymanie indeksów w pamięci RAM jest ważne. Czy jest jeszcze coś, co powinienem rozważyć?
- W pewnym momencie prawdopodobnie będę musiał podzielić moje dane na partycje i korzystać z wielu serwerów. Czy mój przypadek użycia wydaje się, że jest już w tej kategorii, czy też będę mógł przez jakiś czas przeskalować pojedynczą maszynę? Czy to zadziała z 10-krotnością danych? 100x?
Odpowiedzi:
Czy próbowałeś zgromadzić więcej danych i przeprowadzić ich analizę? 100 000 wierszy jest nieistotne. Wypróbuj 250M lub 500M, tak jak się spodziewasz, że będziesz musiał poradzić sobie i zobaczyć, gdzie są wąskie gardła.
RDBMS może zrobić wiele rzeczy, jeśli zwrócisz szczególną uwagę na ograniczenia i spróbujesz pracować z mocnymi stronami systemu. Są wyjątkowo dobre w niektórych sprawach, a okropne w innych, więc musisz eksperymentować, aby upewnić się, że jest to właściwe dopasowanie.
W przypadku niektórych zadań przetwarzania wsadowego tak naprawdę nie można pobić płaskich plików, ładować danych do pamięci RAM, rozbijać je za pomocą serii pętli i zmiennych tymczasowych, a także wyrzucać wyniki. MySQL nigdy nie będzie w stanie dopasować się do tego rodzaju prędkości, ale jeśli zostanie odpowiednio dostrojony i użyty poprawnie, może osiągnąć rząd wielkości.
Musisz zbadać, w jaki sposób można podzielić dane na partycje. Czy masz jeden duży zestaw danych ze zbyt dużą ilością linków, aby móc je rozdzielić, czy też istnieją naturalne miejsca, w których można je podzielić? Jeśli możesz go podzielić, nie będziesz mieć jednego stołu z całym stosem rzędów, ale potencjalnie wiele znacznie mniejszych. Mniejsze tabele, ze znacznie mniejszymi indeksami, zwykle działają lepiej.
Z perspektywy sprzętowej musisz przetestować, aby zobaczyć, jak działa Twoja platforma. Czasami pamięć jest niezbędna. Innym razem jest to dysk I / O. To naprawdę zależy od tego, co robisz z danymi. Musisz zwrócić szczególną uwagę na wykorzystanie procesora i poszukać wysokiego poziomu operacji wejścia / wyjścia, aby dowiedzieć się, gdzie leży problem.
O ile to możliwe, dziel dane na wiele systemów. Możesz użyć klastra MySQL, jeśli czujesz się odważny, lub po prostu rozpędzić wiele niezależnych instancji MySQL, w których każda przechowuje dowolną część pełnego zestawu danych przy użyciu jakiegoś sensownego schematu partycjonowania.
źródło
Tabele podsumowujące.
Codziennie obliczaj zagregowane informacje dla danych dnia. Umieść to w tabelach „podsumowujących”. Odpowiadaj na nie. Łatwo 10 razy szybszy.
W celu dalszej dyskusji proszę podać
Niektóre oczywiste rzeczy ...
„Mniejszy -> bardziej buforowalny -> szybszy
źródło
W przypadku serwowania danych frontonu, chyba że przez cały czas pojawiają się plamki wstawek, naprawdę nie można pokonać wyzwalaczy do wstawiania do zmaterializowanych widoków, które są zsynchronizowane z zapleczem, ale zoptymalizowane do obsługi danych. Oczywiście w tych wyzwalaczach należy ograniczyć do minimum liczbę dołączeń itp. Jedną ze strategii, którą zastosowałem, jest umieszczenie tych wstawek / aktualizacji w kolejce w tabeli pośredniej, a następnie wysyłanie ich co jakiś czas później. Wysyłanie jednego rekordu jest znacznie łatwiejsze niż 4 GB. Przesyłanie strumieniowe danych o wielkości 4 GB zajmuje dużo czasu, nawet jeśli można szybko znaleźć poszukiwane rekordy.
Zgadzam się z tadmanem. Najlepiej jest sprofilować je za pomocą danych, których oczekujesz w pożądanym systemie.
źródło