Mam zestaw danych zawierający 1-minutowe dane 1000 zapasów od 1998 r., Które łącznie dotyczą (2012-1998)*(365*24*60)*1000 = 7.3 Billion
wierszy.
Przez większość (99,9%) czasu będę wykonywać tylko żądania odczytu .
Jaki jest najlepszy sposób przechowywania tych danych w bazie danych?
- 1 duży stół z 7,3 mld rzędów?
- 1000 tabel (po jednej na każdy symbol giełdowy) z 7,3 mln wierszy każdy?
- jakieś zalecenia dotyczące silnika bazy danych? (Planuję używać MySQL Amazon RDS)
Nie jestem przyzwyczajony do zajmowania się tak dużymi zbiorami danych, więc jest to dla mnie doskonała okazja do nauki. Będę wdzięczny za pomoc i rady.
Edytować:
To jest przykładowy wiersz:
„XX”, 20041208, 938, 43,7444, 43,7541, 43,735, 43,7444, 35116,7, 1, 0, 0
Kolumna 1 to symbol giełdowy, kolumna 2 to data, kolumna 3 to minuta, reszta to ceny otwarcia-najwyższego-niskiego-zamknięcia, wolumen i 3 kolumny całkowite.
Większość zapytań będzie brzmiała następująco: „Podaj ceny AAPL między 12 kwietnia 2012 12:15 a 13 kwietnia 2012 12:52”
O sprzęcie: Planuję używać Amazon RDS, więc jestem elastyczny w tym zakresie
Odpowiedzi:
Opowiedz nam o zapytaniach i środowisku sprzętowym.
Byłbym bardzo kuszony, aby przejść do NoSQL , używając Hadoop lub czegoś podobnego, o ile możesz skorzystać z równoległości.
Aktualizacja
OK, dlaczego?
Przede wszystkim zwróć uwagę, że pytałem o pytania. Nie możesz - a my na pewno nie możemy - odpowiedzieć na te pytania, nie wiedząc, jakie jest obciążenie pracą. (Przypadkowo wkrótce ukażę się artykuł na ten temat, ale nie mogę go dziś połączyć). Ale skala problemu sprawia, że myślę o odejściu od dużej starej bazy danych, ponieważ
Moje doświadczenie z podobnymi systemami sugeruje, że dostęp będzie albo duży, sekwencyjny (obliczenie pewnego rodzaju analizy szeregów czasowych), albo bardzo elastyczny eksploracja danych (OLAP). Dane sekwencyjne mogą być lepiej i szybciej przetwarzane sekwencyjnie; OLAP oznacza obliczanie wielu, wielu indeksów, co zajmie dużo czasu lub zajmie dużo miejsca.
Jeśli jednak robisz to, co jest efektywnie dużym przebiegiem dla wielu danych w świecie OLAP, najlepsze może być podejście zorientowane na kolumny.
Jeśli chcesz wykonywać losowe zapytania, w szczególności przeprowadzać porównania krzyżowe, skuteczny może być system Hadoop. Czemu? Dlatego
Ale faktem jest, że dopóki nie dowiemy się o Twoim nakładzie pracy, nie można powiedzieć niczego ostatecznego.
źródło
Zatem bazy danych są przeznaczone do sytuacji, w których masz duży, skomplikowany schemat, który stale się zmienia. Masz tylko jedną „tabelę” z garścią prostych pól numerycznych. Zrobiłbym to w ten sposób:
Przygotuj strukturę C / C ++ do przechowywania formatu rekordu:
Następnie oblicz sizeof (cena magazynowa [N]), gdzie N to liczba rekordów. (W systemie 64-bitowym) Powinien to być tylko kilkaset koncertów i zmieścić się na dysku twardym za 50 USD.
Następnie obetnij plik do tego rozmiaru i mmap (w systemie Linux lub użyj CreateFileMapping w systemie Windows) do pamięci:
Przerzuć wskaźnik mmaped na StockPrice * i prześlij dane, wypełniając tablicę. Zamknij mmap, a teraz będziesz mieć swoje dane w jednej dużej tablicy binarnej w pliku, który można później ponownie skopiować.
Możesz teraz mmap go ponownie w trybie tylko do odczytu z dowolnego programu, a Twoje dane będą łatwo dostępne:
Więc teraz możesz traktować to jak tablicę struktur w pamięci. Możesz tworzyć różne rodzaje indeksowych struktur danych w zależności od tego, jakie są Twoje „zapytania”. Jądro poradzi sobie z przezroczystą zamianą danych na / z dysku, dzięki czemu będzie niesamowicie szybkie.
Jeśli spodziewasz się określonego wzorca dostępu (na przykład ciągłej daty), najlepiej posortować tablicę w tej kolejności, aby trafiała na dysk sekwencyjnie.
źródło
Jednokrotne przechowywanie i wielokrotne odczytywanie danych liczbowych opartych na czasie to przypadek użycia określany jako „szeregi czasowe”. Inne typowe szeregi czasowe to dane z czujników w Internecie rzeczy, statystyki monitorowania serwera, zdarzenia aplikacji itp.
To pytanie zadano w 2012 r. I od tego czasu kilka silników baz danych opracowywało funkcje przeznaczone specjalnie do zarządzania szeregami czasowymi. Osiągnąłem świetne wyniki z InfluxDB , która jest open source, napisana w Go i na licencji MIT.
InfluxDB została specjalnie zoptymalizowana pod kątem przechowywania i odpytywania danych szeregów czasowych. Znacznie bardziej niż Cassandra , która jest często reklamowana jako doskonała do przechowywania szeregów czasowych:
Optymalizacja pod kątem szeregów czasowych wymagała pewnych kompromisów. Na przykład:
W benchmarkach open source ,
Zapytania są również bardzo proste. Jeśli wyglądają Twoje wiersze
<symbol, timestamp, open, high, low, close, volume>
, za pomocą InfluxDB możesz je przechowywać, a następnie łatwo wykonywać zapytania. Powiedzmy, dane z ostatnich 10 minut:Nie ma żadnych identyfikatorów, kluczy ani połączeń do wykonania. Możesz zrobić wiele interesujących agregacji . Nie musisz partycjonować tabeli w pionie, jak w przypadku PostgreSQL , ani przekształcać schematu w tablice sekund, jak w przypadku MongoDB . Ponadto InfluxDB kompresuje naprawdę dobrze, podczas gdy PostgreSQL nie będzie w stanie wykonać żadnej kompresji na typie posiadanych danych .
źródło
W porządku, więc to jest nieco oddalone od innych odpowiedzi, ale ... wydaje mi się, że jeśli masz dane w systemie plików (być może jeden zapas na plik) ze stałym rozmiarem rekordu, możesz uzyskać dane naprawdę łatwo: mając zapytanie o określony czas i zakres czasowy, możesz znaleźć odpowiednie miejsce, pobrać wszystkie potrzebne dane (będziesz dokładnie wiedzieć, ile bajtów), przekształcić dane w wymagany format (co może bądź bardzo szybki w zależności od formatu przechowywania) i jesteś daleko.
Nie wiem nic o pamięci masowej Amazon, ale jeśli nie masz bezpośredniego dostępu do plików, możesz w zasadzie mieć bloby - musiałbyś zrównoważyć duże obiekty blob (mniej rekordów, ale prawdopodobnie odczytuje więcej danych niż potrzebujesz każdego time) z małymi obiektami blob (więcej rekordów oznacza więcej narzutów i prawdopodobnie więcej żądań ich uzyskania, ale za każdym razem zwracanych jest mniej bezużytecznych danych).
Następnie dodajesz buforowanie - sugerowałbym na przykład udostępnienie różnym serwerom różnych zasobów do obsługi - i możesz po prostu obsługiwać z pamięci. Jeśli możesz sobie pozwolić na wystarczającą ilość pamięci na wystarczającej liczbie serwerów, pomiń część „obciążenie na żądanie” i po prostu załaduj wszystkie pliki podczas uruchamiania. Uprościłoby to sprawę kosztem wolniejszego uruchamiania (co oczywiście wpływa na przełączanie awaryjne, chyba że możesz sobie pozwolić na zawsze posiadanie dwóch serwerów dla dowolnego konkretnego magazynu, co byłoby pomocne).
Pamiętaj, że nie musisz przechowywać symbolu giełdowego, daty ani minuty dla każdego rekordu - ponieważ są one niejawne w ładowanym pliku i pozycji w pliku. Powinieneś także rozważyć, jakiej dokładności potrzebujesz dla każdej wartości i jak ją efektywnie przechowywać - w swoim pytaniu podałeś 6SF, który możesz zapisać w 20 bitach. Potencjalnie przechowuj trzy 20-bitowe liczby całkowite w 64 bitach pamięci: przeczytaj je jako
long
(lub cokolwiek będzie to twoja 64-bitowa wartość całkowita) i użyj maskowania / przesuwania, aby przywrócić ją do trzech liczb całkowitych. Będziesz oczywiście musiał wiedzieć, jakiej skali użyć - którą prawdopodobnie możesz zakodować w wolnych 4 bitach, jeśli nie możesz jej ustawić jako stałej.Nie powiedziałeś, jak wyglądają pozostałe trzy kolumny z liczbami całkowitymi, ale jeśli udałoby ci się uciec z 64 bitami również dla tych trzech, możesz zapisać cały rekord w 16 bajtach. To tylko ~ 110 GB dla całej bazy danych, czyli niewiele ...
EDYCJA: Inną rzeczą do rozważenia jest to, że prawdopodobnie akcje nie zmieniają się w ciągu weekendu - a nawet z dnia na dzień. Jeśli giełda jest otwarta tylko 8 godzin dziennie, 5 dni w tygodniu, potrzebujesz tylko 40 wartości tygodniowo zamiast 168. W tym momencie możesz mieć tylko około 28 GB danych w swoich plikach ... co brzmi dużo mniejszy niż początkowo sądziłeś. Posiadanie takiej ilości danych w pamięci jest bardzo rozsądne.
EDYCJA: Myślę, że przegapiłem wyjaśnienie, dlaczego to podejście jest dobre tutaj: masz bardzo przewidywalny aspekt dla dużej części danych - indeks giełdowy, data i godzina. Wyrażając raz znacznik (jako nazwę pliku) i pozostawiając datę / godzinę całkowicie niejawną w pozycji danych, usuwasz całą masę pracy. To trochę jak różnica między a
String[]
i aMap<Integer, String>
- świadomość, że indeks tablicy zawsze zaczyna się od 0 i rośnie w przyrostach o 1 do długości tablicy, pozwala na szybki dostęp i bardziej wydajne przechowywanie.źródło
Rozumiem, że HDF5 został zaprojektowany specjalnie do przechowywania szeregów czasowych danych giełdowych jako jednej potencjalnej aplikacji. Inni badacze wykazali, że HDF5 jest dobry w przypadku dużych ilości danych: chromosomy , fizyka .
źródło
Oto próba stworzenia Market Data Server na bazie bazy danych Microsoft SQL Server 2012, która powinna być dobra do analizy OLAP, darmowego projektu open source:
http://github.com/kriasoft/market-data
źródło
Po pierwsze, nie ma 365 dni handlowych w roku, ze świętami 52 weekendy (104) = powiedzmy 250 x rzeczywista godzina otwarcia rynku, jak ktoś powiedział, a używanie symbolu jako klucza głównego nie jest dobrym pomysłem ponieważ symbole się zmieniają, użyj k_equity_id (numeryczny) z symbolem (char), ponieważ symbole mogą być takie jak to A lub GAC-DB-B.TO, to w tabelach danych z informacjami o cenach masz, więc szacunek 7,3 miliarda jest znacznie przesadzone, ponieważ to tylko około 1,7 miliona wierszy na symbol przez 14 lat.
k_equity_id k_date k_minute
i dla tabeli EOD (która będzie wyświetlana 1000x w porównaniu z innymi danymi)
k_equity_id k_date
Po drugie, nie przechowuj danych OHLC według minut w tej samej tabeli DB, co i tabeli EOD (koniec dnia), ponieważ każdy, kto chce spojrzeć na wykres pnf lub liniowy, w okresie roku, nie ma żadnego zainteresowania najdrobniejsze informacje.
źródło
Pozwól, że polecę Ci przyjrzeć się rozwiązaniu Apache Solr , które moim zdaniem byłoby idealne dla Twojego konkretnego problemu. Zasadniczo należy najpierw zindeksować dane (każdy wiersz jest „dokumentem”). Solr jest zoptymalizowany pod kątem wyszukiwania i natywnie obsługuje zapytania zakresowe dotyczące dat. Twoje nominalne zapytanie,
"Give me the prices of AAPL between April 12 2012 12:15 and April 13 2012 12:52"
przetłumaczyłoby się na coś takiego:
Zakładając, że „stock” to nazwa akcji, a „date” to „DateField” utworzona z kolumn „data” i „minuta” danych wejściowych dotyczących indeksowania. Solr jest niesamowicie elastyczny i naprawdę nie mogę powiedzieć o nim wystarczająco dobrych rzeczy. Na przykład, jeśli trzeba zachować pola w oryginalnych danych, prawdopodobnie można znaleźć sposób na dynamiczne utworzenie pola „DateField” w ramach zapytania (lub filtru).
źródło
Myślę, że każdy większy RDBMS poradziłby sobie z tym. Na poziomie atomowym jedna tabela z prawidłowym partycjonowaniem wydaje się rozsądna (partycja oparta na wykorzystaniu danych, jeśli została naprawiona - jest to prawdopodobnie symbol lub data).
Możesz również przyjrzeć się tworzeniu zagregowanych tabel, aby uzyskać szybszy dostęp powyżej poziomu atomowego. Na przykład, jeśli dane pochodzą z dnia, ale często otrzymujesz dane z powrotem na poziomie tygodnia lub nawet miesiąca, można to wstępnie obliczyć w tabeli zbiorczej. W niektórych bazach danych można to zrobić za pomocą widoku buforowanego (różne nazwy dla różnych rozwiązań baz danych - ale w zasadzie jest to widok danych atomowych, ale po uruchomieniu widok jest buforowany / utwardzany w stałej tabeli tymczasowej - która jest odpytywana o kolejne pasujące zapytania . Można to upuszczać w odstępach czasu, aby zwolnić pamięć / miejsce na dysku).
Wydaje mi się, że moglibyśmy Ci bardziej pomóc z jakimś pomysłem na wykorzystanie danych.
źródło
Powinieneś porównać wolne rozwiązania z prostym modelem zoptymalizowanym w pamięci. Nieskompresowany mieści się w 256 GB serwerze RAM. Migawka mieści się w 32 kB i po prostu indeksujesz ją pozycjonowaniem według daty i godziny. Następnie możesz tworzyć wyspecjalizowane migawki, ponieważ otwarcie jednej często jest równoznaczne z zamknięciem poprzedniej.
[edytuj] Jak myślisz, dlaczego w ogóle sensowne jest używanie bazy danych (rdbms lub nosql)? Te dane się nie zmieniają i mieszczą się w pamięci. To nie jest przypadek użycia, w którym dbms może dodać wartość.
źródło
Jeśli masz sprzęt, polecam MySQL Cluster . Otrzymujesz interfejs MySQL / RDBMS, który znasz, i otrzymujesz szybkie i równoległe zapisy. Odczyty będą wolniejsze niż zwykłe MySQL ze względu na opóźnienia w sieci, ale masz tę zaletę, że możesz zrównoleglać zapytania i odczyty ze względu na sposób działania klastra MySQL i silnika pamięci masowej NDB.
Upewnij się jednak, że masz wystarczającą liczbę maszyn MySQL Cluster i wystarczającą ilość pamięci / RAM dla każdego z nich - MySQL Cluster to silnie zorientowana na pamięć architektura bazy danych.
Lub Redis , jeśli nie masz nic przeciwko interfejsowi klucz-wartość / NoSQL do odczytów / zapisów. Upewnij się, że Redis ma wystarczającą ilość pamięci - jest superszybki do odczytu i zapisu, możesz z nim wykonywać podstawowe zapytania (choć nie-RDBMS), ale jest także bazą danych w pamięci.
Jak powiedzieli inni, pomocna będzie wiedza o zapytaniach, które będziesz wykonywać.
źródło
Będziesz chciał, aby dane były przechowywane w kolumnowej tabeli / bazie danych . Systemy baz danych, takie jak Vertica i Greenplum, są bazami kolumnowymi i uważam, że SQL Server pozwala teraz na tabele kolumnowe. Są one niezwykle wydajne w przypadku
SELECT
bardzo dużych zbiorów danych. Są również wydajne w importowaniu dużych zbiorów danych.Bezpłatną kolumnową bazą danych jest MonetDB .
źródło
Jeśli Twoim przypadkiem użycia jest proste odczytywanie wierszy bez agregacji, możesz użyć klastra Aerospike. Jest w bazie danych pamięci z obsługą systemu plików dla trwałości. Jest również zoptymalizowany pod kątem SSD.
Jeśli Twój przypadek użycia wymaga danych zagregowanych, przejdź do klastra Mongo DB z fragmentowaniem zakresu dat. Dane dotyczące roku można zbierać w odłamkach.
źródło