Używać MySQL do regularnego wykonywania połączeń wielokierunkowych na stołach o pojemności ponad 100 GB?


11

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:

  1. 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.
  2. 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 :

  1. Czy to podejście wydaje się uzasadnione? Czy jest z tym coś złego z dużej perspektywy?
  2. 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?
  3. 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.
  4. 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ć?
  5. 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?

Trudno jest dokładnie odpowiedzieć na to pytanie. Być może lepiej jest badać ogólnie charakterystykę wydajności zapytań MySQL, aby wiedzieć, czego się spodziewać; Jedną rzeczą, którą zawsze możesz zrobić, jest oczywiście umieszczenie 20 dysków na serwerze, abyś mógł czytać z prędkością około 3 GB / s. Ale myślę, że szukasz dokładnej odpowiedzi tylko na oprogramowanie.
usr

Odpowiedzi:


4

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.


@tadman Dziękuję za radę. Zdaję sobie sprawę, że nic nie zastąpi wypróbowania tego. Nie porównałem go z 250 milionami wierszy, ponieważ najpierw chciałem się upewnić, że w moim podejściu nie ma nic oczywistego. Wygląda na to, że nie ma. Ponadto uzyskanie tak dużej ilości danych i wykonanie ich w sposób nieco realistyczny jest wyzwaniem, którego jeszcze nie wymyśliłem. Mam kilka potencjalnych sposobów partycjonowania danych. Myślę, że następnie spróbuję po prostu zwiększyć swoje dane i zobaczyć, jak to działa w różnych punktach kontrolnych - 1M, 10M, 100M itp.
xnickmx

1

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ć

  • POKAŻ UTWÓRZ TABELĘ (w obecnej formie)
  • Rozmiary tabel (o których wspomniałeś)
  • Proponowane WYBORY

Niektóre oczywiste rzeczy ...

  • BIGINT jest rzadko uzasadniony. Zajmuje 8 bajtów. INT UNSIGNED przyjmuje 4 i dopuszcza wartości 0..4 miliardów. I jest MEDIUMINT itp.
  • Wiele indeksów w tabeli „faktów” stanowi zwykle poważny problem z wydajnością, szczególnie w przypadku INSERT. Czy masz tam problem?
  • DATETIME wynosi 8 bajtów; TIMESTAMP to 4
  • Jawne KLUCZOWE OBCIĄŻENIA ZAGRANICZNE są ładne, ale kosztowne
  • DOŁĄCZENIA mogą stanowić problem z wydajnością; trzeba zobaczyć WYBIERZ i UTWÓRZ.
  • 100 GB to niezły rozmiar jak na „dużą” bazę danych MySQL; Podejrzewam, że można by go uruchomić bez Hadoopa itp. Teraz mam do czynienia z jednym takim db - większość stron interfejsu użytkownika odpowiada w ciągu sekundy, mimo że dane są dość zaangażowane.
  • Czy w pewnym momencie będziesz czyścić dane? (Prowadzi to do głównego przypadku użycia dla PARTYCJONOWANIA).

„Mniejszy -> bardziej buforowalny -> szybszy


0

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.


Jak wspomniałem w moim poście, widoki zależą od zapytania, które wykorzystuje cztery sprzężenia w tabelach z dziesiątkami milionów rekordów, więc tak naprawdę nie widzę, jak pomoże widok zmaterializowany.
xnickmx

Wyzwalacze mogą nie być wystarczająco szybkie dla bazy danych tego rozmiaru. Ile WSTAWEK na sekundę się dzieje?
Rick James,

1
@xnickmx Jeśli nie ma tak wielu wstawień / aktualizacji, wyzwalacze ułatwiają / wydajnie utrzymują synchronizowane dane zdenormalizowane. Jeśli trzeba wstawiać / aktualizować szybciej, ustaw je w kolejce w taki sposób: blog.shlomoid.com/2008/04/… lub upiecz własne. W ten sposób nie musisz łączyć się z istniejącymi 100 milionami tabel wierszy, aby uzyskać nowe dane, ponieważ po uruchomieniu wyzwalacza korzystasz z faktu, że znasz nowe dane w tym momencie i możesz po prostu zdenormalizować je jako część tx lub ustaw w kolejce do denormalizacji później.
wes.stueve

@RickJames zgodził się. Musisz wziąć pod uwagę liczbę wstawek dla tego rodzaju strategii i szybkość ich przetwarzania.
wes.stueve
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.