Czy MySQL może rozsądnie wykonywać zapytania na miliardach wierszy?


283

Planuję przechowywać skany ze spektrometru masowego w bazie danych MySQL i chciałbym wiedzieć, czy przechowywanie i analiza tej ilości danych jest zdalnie możliwa. Wiem, że wydajność różni się bardzo w zależności od środowiska, ale szukam przybliżonego rzędu wielkości: czy zapytania potrwają 5 dni, czy 5 milisekund?

Format wejściowy

Każdy plik wejściowy zawiera jeden przebieg spektrometru; każdy przebieg składa się z zestawu skanów, a każdy skan ma uporządkowaną tablicę punktów danych. Jest trochę metadanych, ale większość pliku składa się z tablic 32- lub 64-bitowych liczb całkowitych lub zmiennoprzecinkowych.

System hosta

| ---------------- + ------------------------------- |
| OS | Windows 2008 64-bit |
| Wersja MySQL | 5.5.24 (x86_64) |
| CPU | 2x Xeon E5420 (łącznie 8 rdzeni) |
| RAM | 8 GB |
| System plików SSD | 500 GiB |
| HDD RAID | 12 TiB |
| ---------------- + ------------------------------- |

Istnieje kilka innych usług działających na serwerze, które wykorzystują znikomy czas procesora.

Statystyki plików

| ------------------ + -------------- |
| liczba plików | ~ 16 000 |
| całkowity rozmiar | 1,3 TiB |
| minimalny rozmiar | 0 bajtów |
| maksymalny rozmiar | 12 GiB |
| znaczy | 800 MiB |
| mediana | 500 MiB |
| ogółem punktów danych | ~ 200 miliardów |
| ------------------ + -------------- |

Całkowita liczba punktów danych jest bardzo przybliżona.

Proponowany schemat

Planuję robić rzeczy „dobrze” (tj. Normalizować dane jak szalone), a więc miałbym runstabelę, spectratabelę z kluczem obcym do runsi datapointstabelę z kluczem obcym do spectra.

Pytanie o 200 miliardów punktów danych

Zamierzam analizować wiele widm, a może nawet wiele przebiegów, co spowoduje zapytania, które mogą dotknąć milionów wierszy. Zakładając, że indeksuję wszystko poprawnie (co jest tematem na inne pytanie) i nie próbuję przetasować setek MiB w sieci, czy zdalnie jest możliwe, aby MySQL sobie z tym poradził?

dodatkowe informacje

Dane skanowania będą pochodzić z plików w formacie mzML opartym na XML . Mięso tego formatu znajduje się w <binaryDataArrayList>elementach, w których przechowywane są dane. Każde skanowanie tworzy> = 2 <binaryDataArray>elementy, które razem tworzą dwuwymiarową (lub więcej) tablicę formy [[123.456, 234.567, ...], ...].

Dane te są zapisywane jednokrotnie, więc wydajność aktualizacji i bezpieczeństwo transakcji nie stanowią problemu.

Mój naiwny plan dotyczący schematu bazy danych to:

runs stół

| nazwa kolumny | typ |
| ------------- + ------------- |
| id | KLUCZ PODSTAWOWY |
| czas_początkowy | TIMESTAMP |
| nazwa | VARCHAR |
| ------------- + ------------- |

spectra stół

| nazwa kolumny | typ |
| ---------------- + ------------- |
| id | KLUCZ PODSTAWOWY |
| nazwa | VARCHAR |
| indeks | INT |
| typ_ widma | INT |
| reprezentacja | INT |
| run_id | KLUCZ ZAGRANICZNY |
| ---------------- + ------------- |

datapoints stół

| nazwa kolumny | typ |
| ------------- + ------------- |
| id | KLUCZ PODSTAWOWY |
| widmo_id | KLUCZ ZAGRANICZNY |
| mz | DOUBLE |
| liczba_liczb | DOUBLE |
| indeks | INT |
| ------------- + ------------- |

Czy to rozsądne?


Tak więc, jak być może potrafiłeś wnioskować, jestem programistą, a nie biologiem w laboratorium, więc nie znam wiedzy tak dobrze, jak faktyczni naukowcy.

Oto wykres pojedynczego spektrum (skanu) rodzaju danych, z którymi będę miał do czynienia:

Zrzut ekranu przeglądarki

Celem oprogramowania jest ustalenie, gdzie i jak znaczące są szczyty. Używamy zastrzeżonego pakietu oprogramowania, aby to rozgryźć, ale chcemy napisać własny program analityczny (w języku R), abyśmy wiedzieli, co się dzieje pod kartami. Jak widać, ogromna większość danych jest nieciekawa, ale nie chcemy wyrzucać potencjalnie użytecznych danych, które przeoczył nasz algorytm. Kiedy już będziemy mieć listę prawdopodobnych pików, z których jesteśmy zadowoleni, reszta potoku użyje tej listy pików zamiast surowej listy punktów danych. Przypuszczam, że wystarczyłoby przechowywanie nieprzetworzonych punktów danych jako dużego obiektu blob, aby w razie potrzeby można je ponownie przeanalizować, ale zachowując tylko piki jako odrębne wpisy bazy danych. W takim przypadku byłoby tylko kilkadziesiąt pików na widmo, więc szalone skalowanie nie powinno



8
Ponieważ są to nieprzetworzone dane spektrometru masowego z odpytywaniem A / D, zapisywanie ich w bazie danych wydaje się naprawdę głupie. Brałem swoje surowe dane, zrzucałem je, przetwarzałem i zapisywałem przetworzone WYNIKI w bazie danych. Wynikiem byłyby (a) przebiegi zapisywane po jednym przebiegu na rząd, (b) inne dane związane z tymi przebiegami, takie jak krzywe kalibracyjne, oraz (c) rzędy wyników w bazie danych. To wyciąłoby miliardy rzędów wzdęć z twojego projektu. Gdy chcesz ponownie uruchomić wstępną analizę, skutecznie edytujesz niektóre parametry, uruchamiasz gigantyczną operację obliczeniową i zapisujesz nowe wyniki w db.
Warren P

Odpowiedzi:


115

Nie znam się dobrze na twoich potrzebach, ale być może przechowywanie każdego punktu danych w bazie danych jest trochę przesadzone. Brzmi prawie jak podejście do przechowywania biblioteki obrazów poprzez przechowywanie każdego piksela jako osobnego rekordu w relacyjnej bazie danych.

Zasadniczo przechowywanie danych binarnych w bazach danych jest przez większość czasu błędne. Zwykle istnieje lepszy sposób rozwiązania problemu. Przechowywanie danych binarnych w relacyjnej bazie danych nie jest z natury złe, jednak często wady przeważają nad korzyściami. Relacyjne bazy danych, jak sama nazwa wskazuje, najlepiej nadają się do przechowywania danych relacyjnych. Dane binarne nie są relacyjne. Zwiększa rozmiar (często znacznie) baz danych, może zaszkodzić wydajności i może prowadzić do pytań o utrzymanie miliardowych instancji MySQL. Dobrą wiadomością jest to, że istnieją bazy danych szczególnie dobrze nadające się do przechowywania danych binarnych. Jednym z nich, choć nie zawsze oczywistym, jest twój system plików! Po prostu wymyśl strukturę nazw i katalogów plików binarnych,

Innym podejściem byłoby użycie systemu przechowywania opartego na dokumentach dla danych punktów danych (i być może widm) oraz użycie MySQL dla przebiegów (lub może umieszczenie przebiegów w tym samym DB, co inne).


5
Dlaczego przechowywanie danych binarnych w bazie danych jest błędem? (Pytanie częściowo, ponieważ jestem ciekawy, ale także dlatego, że potrafię wymyślić dla niego przypadek użycia).

15
Jeśli dane binarne nie mają wartości indywidualnie, nie powinny być przechowywane jako unikalny wiersz. Piksel 500 x 320 na obrazie jest nieistotny.

1
To bardzo dobra uwaga. Prawdopodobnie powinniśmy przechowywać surowe pliki na wypadek, gdybyśmy musieli później wyciągnąć pliki, ale analogia do przechowywania obrazów jest świetna. Nigdy nie będziemy potrzebować dostępu do każdego punktu danych (chyba że powtórzymy ekstrakcję piku), więc po prostu przechowywanie wyodrębnionych informacji statystycznych byłoby znacznie lepsze.
haxney

107

Kiedyś pracowałem z bardzo dużą bazą danych MySQL (Terabyte +). Największy stół, jaki mieliśmy, miał dosłownie ponad miliard rzędów. To było przy użyciu MySQL 5.0, więc możliwe, że coś się poprawiło.

Zadziałało. MySQL przez większość czasu poprawnie przetwarzał dane. Było to jednak wyjątkowo nieporęczne. (Jeśli chcesz mieć sześć poziomów dostępności z terabajtem danych, nie używaj MySQL. Byliśmy startupem, który nie miał DBA i miał ograniczone fundusze.)

Samo tworzenie kopii zapasowych i przechowywanie danych było wyzwaniem. Jeśli zajdzie taka potrzeba, przywrócenie tabeli zajęłoby kilka dni.

Mieliśmy wiele tabel w przedziale 10–100 milionów wierszy. Wszelkie znaczące dołączenia do tabel były zbyt czasochłonne i trwałyby wiecznie. Napisaliśmy więc procedury składowane, aby „chodzić” po tabelach i łączyć procesy względem zakresów „id”. W ten sposób przetwarzamy dane od 10 do 100 000 wierszy jednocześnie (Połącz z identyfikatorami 1-100 000, a następnie 100 001-200 000 itd.). Było to znacznie szybsze niż połączenie z całym stołem.

Korzystanie z indeksów w bardzo dużych tabelach, które nie są oparte na kluczu podstawowym, jest również znacznie trudniejsze. Mysql 5.0 przechowuje indeksy w dwóch częściach - przechowuje indeksy (inne niż indeks główny) jako indeksy do wartości klucza podstawowego. Tak więc indeksowane wyszukiwania są wykonywane w dwóch częściach: Najpierw MySQL przechodzi do indeksu i pobiera z niego wartości klucza podstawowego, które musi znaleźć, a następnie wykonuje drugie wyszukiwanie indeksu klucza podstawowego, aby ustalić, gdzie są te wartości.

Z tego wynika, że ​​w przypadku bardzo dużych tabel (1-200 milionów plus wiersze) indeksowanie względem tabel jest bardziej restrykcyjne. Potrzebujesz mniej, prostszych indeksów. A nawet wykonywanie prostych instrukcji select, które nie są bezpośrednio w indeksie, nigdy nie wróci. Gdzie klauzule muszą trafić do indeksów lub zapomnieć o tym.

Ale to wszystko powiedziawszy, rzeczy faktycznie działały. Byliśmy w stanie używać MySQL z tymi bardzo dużymi tabelami oraz wykonywać obliczenia i uzyskiwać prawidłowe odpowiedzi.

Próba przeprowadzenia analizy 200 miliardów wierszy danych wymagałaby bardzo wysokiej klasy sprzętu oraz dużo trzymania za ręce i cierpliwości. Utrzymanie kopii zapasowej danych w formacie, który można przywrócić, byłoby znaczącym zadaniem.

Zgadzam się z odpowiedzią srini.venigalla, że normalizacja danych jak szalona może nie być dobrym pomysłem. Wykonanie sprzężeń w wielu tabelach z taką ilością danych otworzy cię na ryzyko sortowania plików, co może oznaczać, że niektóre z twoich zapytań nigdy nie wrócą. Denormalizacja za pomocą prostych liczb całkowitych daje większą szansę na sukces.

Wszystko, co mieliśmy, to InnoDB. Jeśli chodzi o MyISAM vs. InnoDB: Najważniejsze byłoby, aby nie mieszać tych dwóch. Nie można tak naprawdę zoptymalizować serwera pod kątem obu ze względu na sposób buforowania kluczy i innych danych przez MySQL. Wybierz jedną lub drugą dla wszystkich tabel na serwerze, jeśli możesz. MyISAM może pomóc w niektórych problemach z prędkością, ale może nie pomóc w ogólnej pracy DBA, którą należy wykonać - co może być zabójcą.


1
MySQL bardzo się poprawił w dziale indeksów (...) od 5.0. Ciekawie byłoby zobaczyć, jak się teraz zachowuje.
Pierścień Ø

70

normalizacja danych jak szalona

Normalizacja danych jak szalony może nie być właściwą strategią w tym przypadku. Zachowaj otwarte opcje, przechowując dane zarówno w postaci znormalizowanej, jak i w postaci zmaterializowanych widoków, które są bardzo odpowiednie dla twojej aplikacji. Kluczem w tego typu aplikacjach NIE jest pisanie zapytań adhoc. Modelowanie zapytań jest ważniejsze niż modelowanie danych. Zacznij od docelowych zapytań i pracuj nad optymalnym modelem danych.

Is this reasonable?

Stworzyłbym również dodatkową płaską tabelę ze wszystkimi danymi.

run_id | spectrum_id | data_id | <data table columns..> |

Użyję tej tabeli jako podstawowego źródła wszystkich zapytań. Powodem jest unikanie konieczności łączenia. Połączenia bez indeksowania sprawią, że twój system będzie bardzo bezużyteczny, a indeksowanie tak dużych plików będzie równie straszne.

Strategia polega na tym, że najpierw zapytaj o powyższą tabelę, zrzuć wyniki do tabeli tymczasowej i dołącz do tabeli tymczasowej za pomocą tabel wyszukiwania Run i Spectrum i uzyskaj potrzebne dane.


Czy przeanalizowałeś swoje potrzeby w zakresie zapisu w porównaniu do potrzeb w zakresie odczytu? Bardzo kuszące będzie porzucenie SQL i przejście do niestandardowych mechanizmów przechowywania danych. Moim zdaniem powinna to być ostateczność.

Aby przyspieszyć prędkości zapisu, możesz wypróbować metodę Handler Socket. Percona, o ile pamiętam, pakuje moduł Handler Socket w pakiet instalacyjny. (brak związku z Perconą!)

http://yoshinorimatsunobu.blogspot.com/2010/10/using-mysql-as-nosql-story-for.html


33

Krótka odpowiedź brzmi „tak” - ponieważ liczba wierszy rośnie wraz ze wzrostem znaczenia wybranego schematu, typów danych i operacji.

To, ile znormalizujesz swoje dane, zależy od operacji, które planujesz wykonać na przechowywanych danych. Szczególnie twoja tabela „punktów danych” wydaje się problematyczna - czy planujesz porównać n-ty punkt z dowolnego widma z m-tym dowolnym innym? Jeśli nie, przechowywanie ich osobno może być pomyłką. Jeśli twoje punkty danych nie są samodzielne, ale mają sens tylko w kontekście powiązanych z nimi widm, nie potrzebujesz KLUCZA PODSTAWOWEGO - wystarczy klucz obcy do widm i wystarczy „n-ta” kolumna (kolumna „indeksu”?) .

Zdefiniuj operacje między i wewnątrz spektrum, które musisz wykonać, a następnie znajdź najtańszy sposób ich wykonania. Jeśli równość jest wszystkim, co jest potrzebne, mogą być zdenormalizowane - być może z pewnymi wstępnie obliczonymi metadanymi statystycznymi, które wspomagają twoje operacje. Jeśli absolutnie potrzebujesz dostępu SQL do poszczególnych punktów danych, upewnij się, że zmniejszysz rozmiar każdego wiersza do minimalnej liczby pól i możliwie najmniejszego typu danych.

Największy MySQL, którym kiedykolwiek osobiście zarządzałem, to ~ 100 milionów wierszy. Przy tym rozmiarze chcesz zachować swoje wiersze, a tym samym pola o stałej wielkości - pozwala to MySQL na wydajne obliczanie pozycji dowolnego wiersza w tabeli przez pomnożenie przez ustalony rozmiar każdego wiersza (myśl arytmetyka wskaźnika) - chociaż dokładne szczegóły zależą od używanego silnika pamięci masowej. Użyj MyISAM, jeśli możesz sobie z tym poradzić, czego brakuje w niezawodności, co rekompensuje szybkość, aw twojej sytuacji powinno wystarczyć. Zamień pola o zmiennej wielkości, takie jak VARCHAR na CHAR (n) i użyj RTRIM () w zapytaniach dotyczących odczytu.

Gdy wiersze tabeli mają ustaloną szerokość, możesz zmniejszyć liczbę bajtów, starannie oceniając liczby całkowite MySQL (niektóre z nich są niestandardowe). Każda 1-bajtowa oszczędność, którą możesz wykorzystać, przekształcając 4-bajtową INT w 3-bajtowy MEDIUMINT pozwala zaoszczędzić ~ 1 MB na milion wierszy - co oznacza mniej dyskowych operacji we / wy i bardziej efektywne buforowanie. Używaj najmniejszych możliwych typów danych, z których możesz uciec . Dokładnie oceń typy zmiennoprzecinkowe i sprawdź, czy możesz zastąpić 8-bajtowe PODWÓJNE bajty 4-bajtowymi PŁYWAKAMI, a nawet <8 bajtowe NUMERY STAŁE . Przeprowadź testy, aby upewnić się, że cokolwiek wybierzesz, nie gryzie Cię później.

W zależności od oczekiwanych właściwości zestawu danych i wymaganych operacji mogą wystąpić dalsze oszczędności w bardziej nietypowych kodowaniach wartości (oczekiwane wzorce / powtórzenia, które można zakodować jako indeks w zestawie wartości, surowe dane, które mogą jedynie znacząco przyczynić się do metadane i zostać odrzucone itp.) - chociaż egzotyczne, nieintuicyjne, destrukcyjne optymalizacje są warte tylko wtedy, gdy wypróbowano każdą inną opcję.

Co najważniejsze, bez względu na to, co ostatecznie zrobisz, nie zakładaj, że wybrałeś idealny schemat, a następnie ślepo zacznij wrzucać 10 milionów rekordów. Dobre projekty wymagają czasu, aby ewoluować. Utwórz duży, ale zarządzalny (powiedzmy, 1-5%) zestaw danych testowych i zweryfikuj poprawność i wydajność swojego schematu. Zobacz, jak działają różne operacje (http://dev.mysql.com/doc/refman/5.0/en/using-explain.html) i upewnij się, że równoważysz schemat, aby faworyzować najczęstsze operacje.

Czy powiedziałem krótko? Ups W każdym razie powodzenia!


23

Wydaje się, że jedynym powodem zniszczenia danych punktu danych z XML (w przeciwieństwie do metadanych, takich jak czas i rodzaj uruchomienia) i do postaci bazy danych, jest analizowanie widm w różnych tablicach - tzn. Być może znalezienie wszystkich działa z określonym podpisem. Tylko Ty znasz swoją domenę problemową, ale może to być podobne do przechowywania muzyki próbkowanej przy 96 kHz z 1 próbką na wiersz. Nie jestem pewien, czy rozmiar jest większy niż sposób wykorzystania danych. Zapytanie o dane byłoby równoznaczne z wypowiedzeniem względnej amplitudy 2 minut do utworu we wszystkich utworach The Beatles. Jeśli znasz rodzaj analiz, które można wykonać, całkiem możliwe jest, że wykonanie ich na sygnałach i przechowywanie tych w metadanych dotyczących przebiegu może mieć większy sens.

Nie jestem również pewien, czy dane źródłowe są rzadkie. Jest całkowicie możliwe, że widmo w bazie danych powinno zawierać tylko niezerowe wpisy, podczas gdy oryginalny XML zawiera zerowe wpisy, więc całkowita liczba wierszy może być znacznie mniejsza niż w danych źródłowych.

Podobnie jak w przypadku wielu pytań, zanim zapytasz o obsługę MySQL w twoim modelu, wycofanie się i spojrzenie na model oraz sposób, w jaki będzie on używany, jest prawdopodobnie bardziej odpowiednie niż martwienie się o wydajność.


Po przejrzeniu aktualizacji pytań, myślę, że model, w którym dane binarne są przechowywane jako BLOB lub tylko wskaźnik do pliku, jest wystarczający i pracuję nad modyfikacją modelu w celu przechowywania danych o znaczących pikach, które zostały zidentyfikowane, gdy dane są po raz pierwszy czytać.


18

Prowadzę usługę analizy internetowej z około 50 serwerami baz danych, z których każdy zawiera wiele tabel o długości ponad 100 milionów wierszy, a kilka z nich ma zwykle ponad miliard wierszy, czasem nawet dwa miliardy (na każdym serwerze).

Wydajność tutaj jest w porządku. To bardzo znormalizowane dane. Jednak - moim głównym problemem podczas czytania jest to, że będziesz znacznie powyżej 4,2 miliarda wierszy dla tych tabel (może nie „uruchomi się”, ale prawdopodobnie dwa pozostałe), co oznacza, że ​​będziesz musiał użyć BIGINT zamiast INT dla klucze podstawowe / obce.

Wydajność MySQL z polami BIGINT w indeksowanej kolumnie jest absurdalnie okropna w porównaniu do INT. Popełniłem błąd, robiąc to raz ze stołem, który, jak sądziłem, może wzrosnąć powyżej tego rozmiaru, a gdy osiągnie kilkaset milionów rzędów, wydajność była po prostu fatalna. Nie mam surowych liczb, ale kiedy mówię źle, mam na myśli zły Windows ME.

Ta kolumna była kluczem podstawowym. Przekształciliśmy go z powrotem w INT i presto magico, wydajność znów była dobra.

Wszystkie nasze serwery w tym czasie pracowały na Debian 5 i MySQL 5.0. Od tego czasu zaktualizowaliśmy do Debiana 6 i Percona MySQL 5.5, więc od tego czasu mogło się poprawić. Ale na podstawie mojego doświadczenia tutaj nie, nie sądzę, aby działało to bardzo dobrze.


17

Niezależnie od tego, czy to działa, zawsze napotkasz ten sam problem z jednym monolitycznym nośnikiem pamięci: dyski są wolne. Przy prędkości 100 MB / s (całkiem nieźle jak na spinning) odczytanie tabeli 1 TB zajmuje 3 godziny ; zakładając, że żadna analiza, poszukiwanie lub inne opóźnienia cię nie spowolnią.

Właśnie dlatego prawie każda instalacja „dużych zbiorów danych” korzysta z pewnego rodzaju rozproszonego magazynu danych. Możesz wydać 8 razy więcej pieniędzy na zbudowanie jednego niesamowitego komputera, aby uruchomić DB, ale jeśli masz dużo danych, które można skanować równolegle, prawie zawsze lepiej jest rozłożyć obciążenie na 8 tańszych komputerów.

Projekty takie jak hadoop zostały zbudowane specjalnie do takich celów. Budujesz klaster całej grupy niedrogich komputerów, rozprowadzasz dane między nimi i równolegle je przesyłasz. To tylko jedno z pół tuzina rozwiązań opartych na tym samym pomyśle, ale jest to bardzo popularne.


13

Hm ... Widzę tylko dwa powody, dla których wybrałbyś taką strukturę danych:

  • naprawdę musisz wykonać dowolny punkt danych w stosunku do wszelkich zapytań o punkty danych
  • zamierzasz wykonywać całą swoją logikę w języku SQL

Sugeruję teraz przyjrzeć się swoim wymaganiom i zweryfikować, czy przynajmniej jedno z powyższych założeń jest prawdziwe. Jeśli żadne z nich nie jest prawdą, po prostu spowalniasz wszystko. W przypadku tego rodzaju zestawu danych sugerowałbym najpierw dowiedzieć się, w jaki sposób oczekuje się dostępu do danych, jakiej dokładności będziesz potrzebować itp. - a następnie zaprojektuj bazę danych wokół nich.

PS: Pamiętaj, że będziesz potrzebował co najmniej 36 + 5 bajtów na punkt danych, więc z punktami danych 200B, które powinny zapewnić co najmniej 8,2 TB wymaganego miejsca.

PPS: Prawdopodobnie nie potrzebujesz idkolumny w datapointstabeli, PRIMARY KEY (spectrum_id, index)prawdopodobnie wystarczy (uważaj, indexmoże być to słowo zastrzeżone)


12

EDYTOWAĆ:

NIE RÓB TO W MYSQL Z DANYMI PRZECHOWYWANYMI NA POJEDYNCZYM DYSKU. Sam odczyt tej ilości danych z jednego nośnika zajmie godziny. Musisz SKALOWAĆ, NIE UP.

I musisz zdenormalizować swoje dane, jeśli chcesz przeprowadzić skuteczną analizę danych. Nie projektujesz tutaj systemu online. Chcesz zgnieść liczby, zaprojektuj odpowiednio.

Oryginalna odpowiedź poniżej linii.


Odpowiedź będzie się różnić w zależności od twoich zapytań, MySQL może nie być najlepszym narzędziem do tego zadania. Możesz przyjrzeć się rozwiązaniu, które można skalować „w górę”, a nie „w górę”. Jeśli chcesz włożyć trochę wysiłku, może powinieneś przyjrzeć się rozwiązaniu Map Reduce, np. Hadoop.

Jeśli chcesz wykonywać więcej zapytań ad hoc , rozwiązanie BigQuery firmy Google może być dla Ciebie odpowiednie. Odpowiednia prezentacja z Google I / O 2012: Crunching Big Data with BigQuery

Tak więc rozwiązanie będzie zależeć od tego, czy jest to jednorazowa sprawa i czy chcesz w rozsądny sposób obsługiwać zapytania ad hoc.


9

Nikt o tym nie wspomniał, stąd moja sugestia. Spójrz na masowo podzielone rozwiązania MySQL . Na przykład zobacz tę bardzo cenioną prezentację tumblr .

Koncepcja jest następująca:

  • Zamiast jednej bardzo dużej bazy danych
  • Używaj wielu małych zawierających części oryginalnych danych

W ten sposób można skalować w poziomie, zamiast próbować poprawić wydajność w pionie. BigTable i GFS Google również używają tanich, skalowanych poziomo węzłów do przechowywania i zapytania o petabajty danych.

Będą jednak kłopoty, jeśli będziesz musiał uruchamiać zapytania dotyczące różnych odłamków.


Jeśli ktoś jest zainteresowany, jakiś czas temu stworzyłem aplikację do tworzenia fragmentów powitania. Zostało to omówione tutaj w poście na blogu. Użyłem RavenDB i C #, ale szczegóły nie mają znaczenia, a pomysł jest taki sam.


7

Na jakiej maszynie będą przechowywane dane? Czy to współużytkowane urządzenia pamięci?

Ostatecznym czynnikiem decydującym o czasie zapytania będą twoje dyski twarde. Bazy danych i ich optymalizatory zapytań zostały zaprojektowane w taki sposób, aby maksymalnie ograniczyć liczbę operacji we / wy dysku. Biorąc pod uwagę, że masz tylko 3 tabele, zostanie to wykonane całkiem niezawodnie.

Prędkości odczytu / zapisu na dysku twardym będą 200-300 razy wolniejsze niż prędkości pamięci. Szukaj dysków twardych o bardzo dużych opóźnieniach i szybkich prędkościach odczytu i zapisu. Jeśli wszystkie te dane znajdują się na jednym dysku 2 TB, prawdopodobnie będziesz długo czekać na zakończenie zapytań. Opóźnienie dysku twardego wynosi ~ 10-15 milisekund, a opóźnienie pamięci jest mniejsze niż 10 nanosekund. Opóźnienie dysku twardego może być 1000-2000x wolniejsze niż opóźnienie pamięci. Poruszanie mechanicznym ramieniem na dysku twardym jest POWOLNE w całym systemie.

Ile masz pamięci RAM? 16 giga bajtów? Powiedzmy, że pozwala to na przechowywanie 32 rekordów. Masz 16000 plików. Jeśli zamierzasz skanować liniowo wszystkie punkty danych, możesz z łatwością skończyć z samym czasem wyszukiwania 5-10 sekund. Następnie uwzględnić szybkość transferu 50 Mb / s? Około 7 godzin Ponadto wszelkie tymczasowo zapisane dane będą musiały być przechowywane na dysku twardym, aby zrobić miejsce na odczyt nowych danych.

Jeśli korzystasz ze wspólnego urządzenia pamięci masowej, które jest aktywnie wykorzystywane przez innych użytkowników ... najlepszym rozwiązaniem będzie uruchomienie wszystkiego w nocy.

Pomaga również zmniejszyć liczbę zagnieżdżonych zapytań. Zagnieżdżone zapytania powodują utworzenie tabel tymczasowych, które jeszcze bardziej rzucą dysk twardy. Mam nadzieję, że masz dużo miejsca na dysku twardym.

Optymalizacja zapytania może uwzględniać tylko 1 zapytanie naraz. Dlatego zagnieżdżone instrukcje select nie mogą być zoptymalizowane. JEDNAK, jeśli wiesz, że określone zapytanie zagnieżdżone spowoduje zwrócenie małego zestawu danych, zachowaj je. Optymalizacja zapytania wykorzystuje histogramy i przybliżone założenia, jeśli wiesz coś o danych i zapytaniu, zrób to.

Im więcej wiesz o sposobie przechowywania danych na dysku, tym szybciej będziesz w stanie pisać zapytania. Jeśli wszystko było przechowywane sekwencyjnie na kluczu podstawowym, może być korzystne posortowanie kluczy podstawowych zwróconych z zagnieżdżonego zapytania. Ponadto, jeśli możesz zmniejszyć zestaw zbiorów danych, które musisz w ogóle przeanalizować, zrób to. W zależności od systemu masz około 1 sekundy transferu danych na plik.

Jeśli zamierzasz zmodyfikować wartości nazw (varchars), zmieniłbym go na typ danych o maksymalnym rozmiarze, zapobiegnie to fragmentacji, a kompromis to tylko kilka dodatkowych bajtów pamięci. Może NVARCHAR z maksimum 100.

Jeśli chodzi o komentarze na temat denormalizacji tabeli. Myślę, że najlepiej będzie przechowywać punkty danych w większych grupach (być może jako widma), a następnie przeprowadzić analizę danych w pythonie lub języku współdziałającym z bazą danych. Chyba że jesteś Kreatorem SQL.


3
Podkreślasz ogromną różnicę w opóźnieniu dysku twardego w stosunku do opóźnienia pamięci, ale twoje liczby są wyłączone 1000 razy. Jeśli dyski twarde mają opóźnienie około 10 ms, a pamięć 10ns, opóźnienia nie różnią się o współczynnik 1000, ale współczynnik 1 000 000!
spectre256

6

Dla mnie to brzmi jak scenariusz użycia, w którym chcesz coś w rodzaju „relacyjnego magazynu kolumn”, jak opisano tutaj .

Być może nie rozumiem projektu, ale jeśli masz do czynienia głównie z dużą kolekcją tablic, przechowywanie ich w typowych tabelach zorientowanych na rzędy oznacza, że ​​każdy element jest podobny do wycinka. Jeśli chcesz spojrzeć na plasterki w typowy sposób, ma to sens, ale może być mniej wydajne, jeśli naprawdę patrzysz na całe kolumny na raz.

Podczas pobierania tablic nie tylko możesz nie musieć łączyć go z inną tabelą wynikającą z normalizacji, ale możesz odzyskać serię jako tablicę, a nie skrót.

Naprawdę mogę nie rozumieć problemu i nawet nie sugeruję konkretnego rozwiązania.

Oto kolejna rozmowa, która może być istotna, nawet jeśli tak naprawdę nie jest to aktualne ani możliwe do wdrożenia rozwiązanie.


6

Polecam spróbować podzielić stół na partycje. Mamy ponad 80 milionów wierszy w jednej tabeli (dane giełdowe) i nie mamy problemów z szybkim dostępem do nich.

W zależności od tego, w jaki sposób zamierzasz przeszukiwać dane, powinieneś zaprojektować swoje partycje. W naszym przypadku data działa dobrze, ponieważ szukamy określonych dat.

http://dev.mysql.com/doc/refman/5.1/en/partitioning-limitations.html

http://www.slideshare.net/datacharmer/mysql-partitions-tutorial


5

Tak ale...

Pracowałem z tabelami, które miały 2 miliardy wierszy. Jednak tylko zapytania korzystające z PK były szybkie.

Co najważniejsze, sprzęt miał wystarczającą ilość pamięci RAM, aby zmieścić całe tabele w pamięci. Kiedy stało się to problemem (w tym czasie maksymalnie 96 GB), zdecydowałem się na partycjonowanie pionowe, utrzymując rozmiar tabeli ustawiony na każdej maszynie na tyle mały, aby nadal mieścił się w pamięci. Ponadto maszyny były połączone światłowodem 10 Gb, więc przepustowość sieci nie stanowiła większego problemu.

BTW. twój schemat wygląda jak coś, co może pasować do rozwiązania NoSQL, używając run_idjako klucza skrótu dla widm i spectrum_idjako klucza skrótu dla punktów danych.


4

O tym temacie pisałem na swoim blogu: http://www.tocker.ca/2013/10/24/improving-the-performance-of-large-tables-in-MySQL.html

Aby powtórzyć niektóre kluczowe punkty:

  • B-drzewa degradują się, gdy stają się większe i nie mieszczą się w pamięci (MySQL nie jest tu sam).
  • InnoDB ma pewne funkcje, które pomagają utrzymać pewną wydajność (buforowanie zmian; poprzednio nazywane „wstawianie bufora”).
  • Partycjonowanie może również pomóc.

W komentarzach do mojego postu Tim Callaghan powiązał z tym: http://www.tokutek.com/resources/benchmark-results/benchmarks-vs-innodb-hdds/#iiBench

Który pokazuje wstawianie 1 miliarda wierszy za pomocą testu porównawczego iibench.

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.