Najlepszy magazyn danych dla miliardów wierszy

86

Muszę mieć możliwość przechowywania małych bitów danych (około 50-75 bajtów) dla miliardów rekordów (~ 3 miliardy / miesiąc przez rok).

Jedynym wymaganiem jest szybkie wstawianie i szybkie wyszukiwanie wszystkich rekordów z tym samym identyfikatorem GUID oraz możliwość dostępu do magazynu danych z .net.

Jestem facetem od SQL Server i myślę, że SQL Server może to zrobić, ale przy całej rozmowie o BigTable, CouchDB i innych rozwiązaniach nosql, brzmi to coraz bardziej jak alternatywa dla tradycyjnego RDBS, może być najlepsza ze względu na optymalizacje dla rozproszone zapytania i skalowanie. Próbowałem Cassandra i biblioteki .net nie kompilują się obecnie lub wszystkie mogą ulec zmianie (wraz z samą Cassandrą).

Przejrzałem wiele dostępnych magazynów danych nosql, ale nie mogę znaleźć takiego, który spełniałby moje potrzeby jako solidna platforma gotowa do produkcji.

Gdybyś musiał przechowywać 36 miliardów małych, płaskich rekordów, aby były dostępne z .net, co byś wybrał i dlaczego?

Jody Powlette
źródło
Tak, moje liczby są poprawne. Obecnie mamy tyle danych napływających do systemu, ale agregujemy je i przechowujemy tylko zliczenia zagregowane, więc tracimy dane dla każdego rekordu i utrzymujemy tylko sumy godzinowe. Ze względu na wymagania biznesowe chcemy, aby każdy rekord był taki, jaki był pierwotnie, czyli 3 miliardy wierszy / miesiąc.
Jody Powlette
Zadałeś kilka dobrych pytań. Odpowiedzi są następujące: 95% czasu pracy jest wystarczające - dane są już opóźnione o zmienną kwotę, więc i tak będę musiał je zsynchronizować po fakcie, więc krótki czas nie jest przyczyną zerwania umowy. Utrata wkładek, a nawet tysiące wkładek, to nie koniec świata. Jednak utrata danych z jednego dnia byłaby dość zła. Spójność też nie jest taka ważna. Zasadniczo po wstawieniu 30 milionów wierszy w ciągu dnia muszę pobrać wszystkie wiersze z tym samym identyfikatorem GUID (może 20 wierszy) i mieć pewność, że wszystkie je odzyskam.
Jody Powlette
Czy zrzucasz 30 milionów wierszy dziennie w codziennych / godzinowych zaplanowanych zadaniach wsadowych, czy też przechodzą one w ciągłym ruchu, jeden po drugim?
Remus Rusanu
Dane pochodzą z witryny FTP ... pliki przychodzą w sposób ciągły, a ja mam proces, który analizuje pliki, a obecnie generuje zagregowane dane i wstawia zagregowane wartości (może 1000 wierszy) jako transakcję. Nowy proces będzie wymagał wstawienia setek tysięcy wierszy z każdego otrzymanego pliku, prawdopodobnie najbardziej efektywnym sposobem byłoby użycie wstawiania zbiorczego.
Jody Powlette
To brzmi jak zadanie ETL dla SSIS i SQL Server. Posiadają rekord świata w ETL, z prędkością wysyłania ponad 2 TB / godzinę: blogs.msdn.com/sqlperf/archive/2008/02/27/etl-world-record.aspx
Remus Rusanu

Odpowiedzi:

102

Przechowywanie ~ 3,5 TB danych i wstawianie około 1 K / s 24x7, a także wykonywanie zapytań z nieokreśloną szybkością, jest to możliwe z SQL Server, ale jest więcej pytań:

  • jakie masz wymagania dotyczące dostępności? 99,999% czasu pracy, czy wystarczy 95%?
  • jakie masz wymagania dotyczące niezawodności? Czy brak wkładki kosztuje 1 milion dolarów?
  • jakie masz wymagania dotyczące możliwości odzyskania? Jeśli stracisz jeden dzień danych, czy to ma znaczenie?
  • jakie masz wymagania dotyczące spójności? Czy należy zagwarantować, że zapis będzie widoczny przy następnym czytaniu?

Jeśli potrzebujesz wszystkich tych wymagań, które podkreśliłem, obciążenie, które proponujesz, będzie kosztować miliony w sprzęcie i licencjonowaniu w systemie relacyjnym, dowolnym systemie, bez względu na to, jakie sztuczki spróbujesz (sharding, partycjonowanie itp.). System nosql z definicji nie spełniałby wszystkich tych wymagań.

Więc oczywiście złagodziłeś już niektóre z tych wymagań. Istnieje przyjemny przewodnik wizualny porównujący oferty nosql w oparciu o paradygmat „wybierz 2 z 3” w Visual Guide to NoSQL Systems :

nosql compareisson

Po aktualizacji komentarza OP

W przypadku SQL Server byłaby to prosta implementacja:

  • jeden klucz klastrowy z pojedynczą tabelą (identyfikator GUID, czas). Tak, ulegnie fragmentacji , ale czy fragmentacja wpłynie na odczyty z wyprzedzeniem, a odczyty z wyprzedzeniem są potrzebne tylko w przypadku skanowania znacznego zasięgu. Ponieważ wyszukujesz tylko określony identyfikator GUID i zakres dat, fragmentacja nie będzie miała większego znaczenia. Tak, jest to klucz szeroki, więc strony nieskładkowe będą miały słabą gęstość klucza. Tak, doprowadzi to do słabego współczynnika wypełnienia. I tak, mogą wystąpić podziały stron. Pomimo tych problemów, biorąc pod uwagę wymagania, nadal najlepszym wyborem jest klaster.
  • podziel tabelę według czasu, aby móc efektywnie usuwać wygasłe rekordy za pomocą automatycznego przesuwanego okna . Uzupełnij to o przebudowę partycji indeksu online z ostatniego miesiąca, aby wyeliminować słaby współczynnik wypełnienia i fragmentację wprowadzoną przez klastrowanie GUID.
  • włącz kompresję strony. Ponieważ najpierw klastrowane są grupy kluczy według identyfikatora GUID, wszystkie rekordy identyfikatora GUID będą znajdować się obok siebie, co daje kompresji strony dużą szansę na wdrożenie kompresji słownika.
  • będziesz potrzebować szybkiej ścieżki we / wy dla pliku dziennika. Interesuje Cię wysoka przepustowość, a nie małe opóźnienia, aby dziennik mógł nadążyć z szybkością 1 tys. Wstawień na sekundę, więc usuwanie elementów jest koniecznością.

Partycjonowanie i kompresja stron wymagają SQL Server Enterprise Edition, nie będą działać w wersji Standard Edition i oba są bardzo ważne, aby spełnić wymagania.

Na marginesie, jeśli rekordy pochodzą z farmy serwerów WWW frontonu, umieściłbym Express na każdym serwerze sieciowym i zamiast INSERT na zapleczu, SENDprzekazałbym informacje do zaplecza, używając lokalnego połączenia / transakcji na urządzeniu Express znajdującym się razem z serwerem WWW. Daje to znacznie lepszą historię dostępności rozwiązania.

Więc tak bym to zrobił w SQL Server. Dobra wiadomość jest taka, że ​​problemy, z którymi się spotkasz, są dobrze rozumiane, a rozwiązania znane. to niekoniecznie oznacza, że ​​jest to lepsze niż to, co można osiągnąć dzięki Cassandrze, BigTable lub Dynamo. Pozwolę komuś, kto jest bardziej kompetentny w sprawach nie-sql-ish, do argumentowania ich racji.

Zauważ, że nigdy nie wspomniałem o modelu programowania, obsłudze .Net i tym podobnych. Szczerze myślę, że nie mają one znaczenia w dużych wdrożeniach. Robią ogromną różnicę w procesie rozwoju, ale po wdrożeniu nie ma znaczenia, jak szybki był rozwój, czy narzut ORM zabija wydajność :)

Remus Rusanu
źródło
Podlinkowałem stronę Nathana, ale to nie jest strona główna slashdot;)
Remus Rusanu
@RemusRusanu: przyglądamy się migracji dba.se. Żeby cię przygotować :-) I +1
gbn
Począwszy od Microsoft SQL Server 2016, edycja Enterprise nie jest już wymagana do partycjonowania tabel, ponieważ partycjonowanie tabel jest teraz dostępne w prawie wszystkich wersjach SQL Server 2016.
TChadwick
17

Wbrew powszechnemu przekonaniu w NoSQL nie chodzi o wydajność ani nawet skalowalność. Chodzi głównie o zminimalizowanie tak zwanego niedopasowania impedancji obiektowo-relacyjnej, ale dotyczy również skalowalności poziomej w porównaniu z bardziej typową skalowalnością pionową RDBMS.

Do prostego wymagania szybkiego wstawiania i szybkiego wyszukiwania wystarczy prawie każdy produkt bazodanowy. Jeśli chcesz dodać dane relacyjne lub sprzężenia, lub masz jakąkolwiek złożoną logikę transakcyjną lub ograniczenia, które musisz egzekwować, potrzebujesz relacyjnej bazy danych. Żaden produkt NoSQL nie może się równać.

Jeśli potrzebujesz danych bez schematów, powinieneś skorzystać z bazy danych zorientowanej na dokumenty, takiej jak MongoDB lub CouchDB. Luźny schemat jest główną atrakcją tych; Osobiście lubię MongoDB i używam go w kilku niestandardowych systemach raportowania. Uważam to za bardzo przydatne, gdy wymagania dotyczące danych stale się zmieniają.

Inną główną opcją NoSQL są rozproszone magazyny klucza i wartości, takie jak BigTable lub Cassandra. Są one szczególnie przydatne, jeśli chcesz skalować bazę danych na wiele maszyn, na których działa zwykły sprzęt. Oczywiście działają dobrze również na serwerach, ale nie korzystają z wysokiej klasy sprzętu, a także SQL Server lub Oracle lub innej bazy danych zaprojektowanej do skalowania pionowego i oczywiście nie są relacyjne i nie nadają się do wymuszania normalizacji lub ograniczenia. Ponadto, jak zauważyłeś, obsługa .NET jest w najlepszym przypadku nierówna.

Wszystkie produkty oparte na relacyjnych bazach danych obsługują ograniczone partycjonowanie. Nie są tak elastyczne jak BigTable lub inne systemy DKVS, nie dzielą się łatwo na setki serwerów, ale naprawdę nie wygląda na to, że tego szukasz. Są całkiem dobre w obsłudze miliardów rekordów, o ile odpowiednio indeksujesz i normalizujesz dane, uruchamiasz bazę danych na potężnym sprzęcie (zwłaszcza dyskach SSD, jeśli możesz sobie na to pozwolić) i dzielisz na 2 lub 3 lub 5 dysków fizycznych, jeśli niezbędny.

Jeśli spełniasz powyższe kryteria, jeśli pracujesz w środowisku korporacyjnym i masz pieniądze do wydania na przyzwoity sprzęt i optymalizację bazy danych, na razie pozostanę przy SQL Server. Jeśli ściskasz grosze i chcesz uruchomić to na słabszym sprzęcie do przetwarzania w chmurze Amazon EC2, prawdopodobnie wolałbyś zamiast tego wybrać Cassandrę lub Voldemorta (zakładając, że możesz pracować z .NET).

Aaronaught
źródło
11

Bardzo niewiele osób pracuje z wielomiliardowym rozmiarem zestawu wierszy, a większość razy, gdy widzę takie żądanie przy przepełnieniu stosu, dane nie są w pobliżu rozmiaru, w jakim są zgłaszane.

36 miliardów, 3 miliardy miesięcznie, to około 100 milionów dziennie, 4,16 miliona na godzinę, ~ 70 tysięcy wierszy na minutę, 1,1 tysiąca wierszy na sekundę wchodzących do systemu, w sposób ciągły przez 12 miesięcy, zakładając brak przestojów.

Te liczby nie są niemożliwe z dużym marginesem, robiłem większe systemy, ale chcesz dokładnie sprawdzić, czy naprawdę chodzi o ilości - bardzo niewiele aplikacji ma taką liczbę.

Jeśli chodzi o przechowywanie / odzyskiwanie i dość krytycznym aspektem, o którym nie wspomniałeś, jest starzenie się starszych danych - usuwanie nie jest darmowe.

Normalną technologią jest partycjonowanie, jednak wyszukiwanie / pobieranie oparte na GUID skutkowałoby niską wydajnością, zakładając, że musisz uzyskać wszystkie pasujące wartości w całym okresie 12 miesięcy. Możesz umieścić klastrowane indeksy w kolumnie GUID, aby uzyskać powiązany klaster danych do odczytu / zapisu, ale przy tych ilościach i szybkości wstawiania fragmentacja będzie o wiele za duża, aby ją obsłużyć, i spadnie na podłogę.

Sugerowałbym również, że będziesz potrzebować bardzo przyzwoitego budżetu na sprzęt, jeśli jest to poważna aplikacja z szybkościami odpowiedzi typu OLTP, to znaczy na podstawie pewnych przybliżonych domysłów, zakładając bardzo niewiele kosztów indeksowania, około 2,7 TB danych.

W obozie SQL Server jedyną rzeczą, na którą warto spojrzeć, jest nowa edycja równoległej hurtowni danych (madison), która jest bardziej zaprojektowana do dzielenia danych na fragmenty i uruchamiania równoległych zapytań w celu zapewnienia dużej szybkości w przypadku dużych datamartów.

Andrzej
źródło
3
W bioinformatyce miliardowe zbiory danych nie są rzadkością. Ale często są obsługiwane w sposób czysto strumieniowy z płaskich plików.
Erik Garrison
3
@Erik: do przetwarzania strumieniowego (tj. Wystarczy wykryć określone warunki, ale nie ma potrzeby przechowywania danych do późniejszego odpytywania) coś takiego jak StreamInsight jest lepsze niż jakakolwiek baza danych microsoft.com/sqlserver/2008/en/us/r2 -complex-event.aspx
Remus Rusanu
2

„Muszę mieć możliwość przechowywania małych bitów danych (około 50-75 bajtów) dla miliardów rekordów (~ 3 miliardy / miesiąc przez rok).

Jedynym wymaganiem jest szybkie wstawianie i szybkie wyszukiwanie wszystkich rekordów z tym samym identyfikatorem GUID oraz możliwość dostępu do magazynu danych z .net ”.

Z doświadczenia mogę powiedzieć, że jest to możliwe w SQL Server, ponieważ zrobiłem to na początku 2009 ... i działa do dziś i dość szybko.

Tabela została podzielona na 256 partycji, pamiętaj, że to była wersja SQL 2005 ... i zrobiliśmy dokładnie to, co mówisz, czyli przechowywanie bitów informacji według GUID i szybkie pobieranie przez GUID.

Kiedy wyszedłem, mieliśmy około 2-3 miliardów rekordów, a odzyskiwanie danych było nadal całkiem dobre (1-2 sekundy, jeśli korzystałem z interfejsu użytkownika, lub mniej, jeśli korzystałem z RDBMS), mimo że polityka przechowywania danych miała właśnie zostać utworzona.

Tak więc, krótko mówiąc, wziąłem 8-ty znak (tj. Gdzieś pośrodku) z ciągu GUID i SHA1 zahaszował go i rzucił jako małe int (0-255) i zapisałem w odpowiedniej partycji i użyłem tego samego wywołania funkcji podczas pobierania dane z powrotem.

daj mi znać, jeśli potrzebujesz więcej informacji ...

Goran B.
źródło
2

W poniższym artykule omówiono importowanie i używanie 16- miliardowej tabeli wierszy w programie Microsoft SQL. http://sqlmag.com/t-sql/adventures-big-data-how-import-16-billion-rows-single-table .

Z artykułu:

Oto kilka destylowanych wskazówek z mojego doświadczenia:

  • Im więcej danych znajduje się w tabeli ze zdefiniowanym indeksem klastrowym, tym wolniej jest importować do niej nieposortowane rekordy. W pewnym momencie staje się to zbyt wolne, aby było praktyczne.
  • Jeśli chcesz wyeksportować tabelę do najmniejszego możliwego pliku, ustaw go w formacie natywnym. Działa to najlepiej w przypadku tabel zawierających głównie kolumny liczbowe, ponieważ są one bardziej zwarte w polach binarnych niż dane znakowe. Jeśli wszystkie Twoje dane są alfanumeryczne, niewiele zyskasz, eksportując je w formacie natywnym. Brak zezwolenia na wartości null w polach numerycznych może dodatkowo skompaktować dane. Jeśli zezwolisz, aby pole dopuszczało wartość null, binarna reprezentacja pola będzie zawierała 1-bajtowy prefiks wskazujący, ile bajtów danych będzie następować.
  • Nie można użyć BCP dla więcej niż 2 147 483 647 rekordów, ponieważ zmienna licznika BCP jest 4-bajtową liczbą całkowitą. Nie udało mi się znaleźć żadnego odniesienia do tego w MSDN ani w Internecie. Jeśli Twoja tabela zawiera
    więcej niż 2 147 483 647 rekordów, będziesz musiał wyeksportować ją w fragmentach
    lub napisać własną procedurę eksportowania.
  • Definiowanie indeksu klastrowego we wstępnie wypełnionej tabeli zajmuje dużo miejsca na dysku. W moim teście mój dziennik eksplodował do 10-krotności pierwotnego
    rozmiaru tabeli przed ukończeniem.
  • Podczas importowania dużej liczby rekordów za pomocą instrukcji BULK INSERT należy dołączyć parametr BATCHSIZE i określić, ile
    rekordów ma zostać zatwierdzonych naraz. Jeśli nie podasz tego parametru,
    cały plik zostanie zaimportowany jako pojedyncza transakcja, która
    wymaga dużo miejsca na dzienniki.
  • Najszybszym sposobem umieszczenia danych w tabeli z indeksem klastrowym jest wstępne posortowanie danych. Następnie można go zaimportować za pomocą
    instrukcji BULK INSERT z parametrem ORDER.
Charles Burns
źródło
1

Istnieje niezwykły fakt, który wydaje się przeoczany.

Zasadniczo po wstawieniu 30 milionów wierszy w ciągu dnia muszę pobrać wszystkie wiersze z tym samym identyfikatorem GUID (może 20 wierszy) i być pewnym, że wszystkie je odzyskam

Potrzebując tylko 20 kolumn, indeks nieklastrowy w identyfikatorze GUID będzie działał dobrze. Możesz skupić się na innej kolumnie w celu rozproszenia danych na partycjach.

Mam pytanie dotyczące wprowadzania danych: W jaki sposób są wstawiane?

  • Czy to jest wstawka zbiorcza według określonego harmonogramu (na minutę, godzinę itp.)?
  • Z jakiego źródła są pobierane te dane (pliki płaskie, OLTP itp.)?

Myślę, że należy odpowiedzieć na te pytania, aby pomóc zrozumieć jedną stronę równania.

Josef Richberg
źródło
1

Amazon Redshift to świetna usługa. Nie był dostępny, gdy pytanie zostało pierwotnie opublikowane w 2010 roku, ale teraz jest głównym graczem w 2017 roku. Jest to baza danych oparta na kolumnach, rozwidlona z Postgres, więc standardowe biblioteki SQL i łączników Postgres będą z nią współpracować.

Najlepiej jest używać go do celów raportowania, zwłaszcza agregacji. Dane z pojedynczej tabeli są przechowywane na różnych serwerach w chmurze firmy Amazon i dystrybuowane według zdefiniowanych kluczy dystrybucyjnych tabeli, więc możesz polegać na rozproszonej mocy procesora.

Zatem SELECT, a zwłaszcza zagregowane SELECT, są błyskawiczne. Ładowanie dużych danych najlepiej wykonać za pomocą polecenia COPY z plików csv Amazon S3. Wadą jest to, że operacje DELETE i UPDATE są wolniejsze niż zwykle, ale właśnie dlatego Redshift nie jest przede wszystkim transnarodową bazą danych, ale raczej platformą hurtowni danych.

Martin Taleski
źródło
0

Możesz spróbować użyć Cassandry lub HBase, ale musisz przeczytać, jak zaprojektować rodziny kolumn zgodnie z Twoim przypadkiem użycia. Cassandra zapewnia własny język zapytań, ale aby uzyskać bezpośredni dostęp do danych, musisz użyć interfejsów API Java platformy HBase. Jeśli potrzebujesz użyć Hbase, polecam przeszukiwanie danych za pomocą Apache Drill z Map-R, który jest projektem Open Source. Język zapytań Drill jest zgodny z SQL (słowa kluczowe w wierszu mają takie samo znaczenie, jak w SQL).

Yayati Sule
źródło
0

Przy tylu rekordach rocznie w końcu zabraknie miejsca. Dlaczego nie pamięć systemu plików, taka jak xfs, która obsługuje 2 ^ 64 plików i używa mniejszych pudełek. Bez względu na to, jak fantazyjni ludzie chcą dostać lub ile pieniędzy w końcu wydałoby się na zakup systemu z dowolną bazą danych SQL NoSQL ... niezależnie od tego, które z tych wielu rekordów są zwykle tworzone przez firmy elektryczne i stacje / dostawcy pogodowe, takie jak ministerstwo środowiska, które kontroluje mniejsze stacje na terenie całego kraju. Jeśli robisz coś takiego, jak przechowywanie ciśnienia, temperatury, prędkości wiatru, wilgotności itp., A przewodnikiem jest lokalizacja, nadal możesz podzielić dane przez rok / miesiąc / dzień / godzinę. Zakładając, że przechowujesz 4 lata danych na dysku twardym. Następnie możesz uruchomić go na mniejszym Nas z lustrem, gdzie zapewniłby również lepszą prędkość odczytu i miał wiele punktów montowania. na podstawie roku, w którym został utworzony. Możesz po prostu utworzyć interfejs sieciowy do wyszukiwania, więc lokalizacja zrzutu 1/2001/06/01 // temperatura i lokalizacja1 / 2002/06/01 // temperature zrzuciłby tylko zawartość godzinowej temperatury pierwszego dnia lata w ciągu tych 2 lat (24h * 2) 48 małych plików w porównaniu z przeszukiwaniem bazy danych z miliardami rekordów i prawdopodobnie wydanymi milionami. Prosty sposób patrzenia na rzeczy ... 1,5 miliarda stron internetowych na świecie, Bóg wie, ile stron każda. Gdyby firma taka jak Google musiała wydać miliony na 3 miliardy wyszukiwań, aby zapłacić za super-komputery, byłaby bankrutem. Zamiast tego mają rachunek za prąd ... kilka milionów gównianych komputerów. I indeksowanie kofeiny ... przyszłościowe ... dodawaj więcej. I tak, gdzie indeksowanie działające poza SQL ma sens, to świetnie Budowanie super-komputerów do beznadziejnych zadań z ustalonymi rzeczami, takimi jak pogoda ... statystyki i tak dalej, aby technicy mogli się pochwalić, że ich systemy chrupią xtb w x sekund ... stratą pieniędzy, które mogą być spędzony gdzie indziej.

Francisco
źródło
-2

Przechowywanie rekordów w zwykłych plikach binarnych, jeden plik na identyfikator GUID, nie byłoby szybsze.

Thomas Kjørnes
źródło
5
Czy naprawdę oczekujesz, że to zadziała?
ChaosPandion
3
Tak, tworzenie miliardów plików w systemie plików może być katastrofalne dla niektórych systemów plików. Popełniłem błąd, robiąc coś takiego, ale mając tylko 1 milion i prawie całkowicie wyłączyłem system, próbując otworzyć powłokę jednego z tych folderów. Poza tym, jeśli nie szukasz wyszukiwania w oparciu o guid, jak ma działać mechanizm zapytań?
Rob Goodwin
Trudno zgadnąć, jak by to wyglądało, nie wiedząc, ile unikalnych identyfikatorów GUID jest oczekiwanych :) Ale nie ma nic prostszego niż zwykłe zapisywanie do zwykłych plików. Jedynym wymaganiem było szybkie wstawianie wraz z wyszukiwaniem według identyfikatora GUID.
Thomas Kjørnes
Może działać, ale musisz ograniczyć liczbę plików w folderze. Musisz wygenerować nowy folder na n plików. Możesz użyć podłańcucha guid jako nazwy folderu.
TTT
1
tak, istnieje ograniczenie liczby i-węzłów dla wielu systemów plików i pamiętam, że ograniczaliśmy się do domyślnego systemu plików redhat .... limit wynosił około 1 000 000 plików.
Dean Hiller
-3

Możesz użyć MongoDB i użyć guid jako klucza fragmentowania, co oznacza, że ​​możesz dystrybuować dane na wielu komputerach, ale dane, które chcesz wybrać, znajdują się tylko na jednym komputerze, ponieważ wybierasz za pomocą klucza fragmentowania.

Sharding w MongoDb nie jest jeszcze gotowy do produkcji.

Theo
źródło