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.