tło
Mam sieć około 2000 czujników, z których każdy ma około 100 punktów danych, które zbieramy co 10 minut. Te punkty danych są zwykle wartościami całkowitymi, ale niektóre są łańcuchami i liczbami zmiennoprzecinkowymi. Te dane powinny być przechowywane przez 90 dni, więcej, jeśli to możliwe i nadal wydajne.
Projektowanie bazy danych
Kiedy pierwotnie zlecono mu ten projekt, napisałem aplikację C #, która napisała pliki oddzielone przecinkami dla każdego czujnika. W tamtym czasie nie było ich tak wiele, gdy ktoś chciał przyjrzeć się trendom, otworzyliśmy plik CSV w programie Excel i zobrazowaliśmy go w razie potrzeby.
Sprawy rosły i przeszliśmy na bazę danych MySQL. Stworzyłem tabelę dla każdego czujnika (tak, wiem, wiele tabel!); działał dobrze, ale ma pewne ograniczenia. Przy tak wielu tabelach oczywiście niemożliwe jest napisanie zapytania, które znajdzie dane wśród wszystkich czujników, gdy szuka się określonej wartości.
W następnej wersji przełączyłem się na Microsoft SQL Server Express i umieściłem wszystkie dane czujnika w jednej dużej tabeli. Działa to również i pozwala nam wyszukiwać wartości wśród wszystkich interesujących czujników. Jednak natrafiłem na limit 10 GB dla wersji Express i zdecydowałem się wrócić do MySQL zamiast inwestować w SQL Server Standard.
Pytanie
Jestem zadowolony z wydajności i skalowalności MySQL, ale nie jestem pewien, czy najlepiej zastosować podejście oparte na danych w jednym stole. 10 GB w jednym stole wydaje się wymagać innego projektu. Powinienem wspomnieć, że nadal istnieje potrzeba zapytania danych o wykresy i obawiam się, że pojawią się problemy z wydajnością zapytania, które przedstawia wykresy, na przykład dane dotyczące temperatury dla jednego czujnika przez pełne 90 dni. (Innymi słowy, wykres powinien być czymś, co można szybko wytworzyć, bez czekania, aż SQL posortuje stosy danych w celu odizolowania sensora).
Czy powinienem w jakiś sposób podzielić tę tabelę, aby zwiększyć wydajność? Czy to nie jest niezwykłe mieć tak duży stół?
Mam indeksy w kolumnach Identyfikator czujnika i Znacznik czasu, co stanowi w zasadzie granice definiujące każde zapytanie. (tzn. uzyskaj dane dla czujnika X od czasu A do czasu B).
Przeczytałem trochę o dzieleniu i dzieleniu na partycje, ale nie sądzę, aby były one odpowiednie w tym przypadku.
Edytować:
Na podstawie dotychczasowych komentarzy i odpowiedzi przydatne mogą być dodatkowe informacje:
Nieokreślony czas przechowywania: obecnie nie przechowuję danych z ostatnich 90 dni. Codziennie uruchamiam zapytanie, które usuwa dane starsze niż 90 dni. Jeśli stanie się to ważne w przyszłości, zgromadzę więcej, ale na razie wystarczy. Pomaga to utrzymać rozmiar pod kontrolą i wysoką (er) wydajność.
Typ silnika: Oryginalna implementacja MySQL używała MyISAM. Tym razem podczas tworzenia tabel dla nowej implementacji (jedna tabela danych zamiast wielu) domyślnie wybrano InnoDB. Nie wydaje mi się, żebym wymagał jednego lub drugiego.
Normalizacja: Istnieją oczywiście inne tabele oprócz tabeli gromadzenia danych. Te tabele wsparcia przechowują takie informacje, jak informacje o sieci dla czujników, dane logowania dla użytkowników itp. Nie ma wiele do normalizacji (o ile mi wiadomo). Tabela danych ma tak wiele kolumn, ponieważ istnieje tyle zmiennych z każdego czujnika. (Wiele temperatur, poziomów światła, ciśnienia powietrza itp.) Normalizacja według mnie oznacza, że nie ma zbędnych danych ani powtarzających się grup. (Przynajmniej dla 1NF.) Dla danego czujnika przechowywanie wszystkich wartości w określonym czasie wymaga jednego wiersza danych i nie ma w tym związku żadnych relacji 1: N (które widzę).
Mógłbym funkcjonalnie rozdzielić tabelę, tworząc (na przykład) wszystkie wartości związane z temperaturą w jednej tabeli, a wszystkie wartości związane z ciśnieniem powietrza w innej. Chociaż może to poprawić wydajność osoby wykonującej zapytanie tylko z temperaturą, nadal muszę wstawić wszystkie dane naraz. Mimo to wzrost wydajności może być opłacalny dla operacji SELECT. Oczywiście lepiej byłoby podzielić tabelę w pionie na podstawie tego, jak często użytkownicy żądają danych. Być może to wszystko, co powinienem zrobić. Wydaje mi się, że zadając moje pytanie, szukam potwierdzenia, że warto byłoby to zrobić.
Edycja 2:
Wykorzystanie danych: Ostatecznie większość danych nigdy nie jest przeglądana ani potrzebna, ponieważ zazwyczaj koncentrujemy się tylko na elementach z problemami. Ale próbując znaleźć problemy, używamy różnych narzędzi do wyszukiwania danych i określania, które elementy należy powiększyć.
Zauważyliśmy na przykład korelację między wartością użycia pamięci (zastrzeżonego oprogramowania klienta) a ponownym uruchomieniem / awarią. Jeden z punktów danych, który zbieram, odnosi się do tego użycia pamięci i mogłem spojrzeć na dane historyczne, aby pokazać, że urządzenia stają się niestabilne po przekroczeniu określonego użycia pamięci. Dzisiaj dla podzbioru urządzeń z tym oprogramowaniem sprawdzam tę wartość i wydaje polecenie ponownego uruchomienia, jeśli jest ona zbyt wysoka. Dopóki tego nie odkryłem, nie sądziłem, że zbieranie tych danych będzie miało wartość.
Z tego powodu utrzymywałem, że około 100 punktów danych jest gromadzonych i przechowywanych, nawet jeśli wartość jest wątpliwa. Ale w normalnym codziennym użytkowaniu użytkownicy zwykle sprawdzają może kilkanaście tych parametrów. Jeśli użytkownik zainteresuje się określonym obszarem geograficznym, może (przy użyciu oprogramowania) generować wykresy lub arkusze danych dla kilkudziesięciu czujników. Nierzadko patrzy się na 30-dniowy wykres z dwiema lub trzema liniami wykresu pokazującymi takie rzeczy, jak temperatura, ciśnienie powietrza i poziomy światła. W ten sposób uruchomione zostanie zapytanie podobne do tego:
SELECT sensor_id, location, data_timestamp, temp1, air1, light1
FROM data
WHERE data_timestamp >= '2012-02-01'
AND sensor_id IN (1, 2, 3);
(W oryginalnej wersji MySQL, w której każdy czujnik miał własną tabelę, wydawane byłyby trzy osobne zapytania, ale wyniki były łączone w oprogramowanie do utworzenia wykresu.)
Ponieważ data
tabela zawiera tak wiele wierszy (~ 10 milionów), pomimo włączonych wskaźników id
i data_timestamp
, wydajność jest wyraźnie gorsza niż scenariusz z wieloma tabelami (4500 wierszy zwróconych w ciągu 9 sekund w przeciwieństwie do mniej niż jednej sekundy w tym przykładzie). Możliwość znalezienia czujników spełniających określone kryteria jest praktycznie zerowa w schemacie wielostołowym, a zatem powodem przejścia do pojedynczego stołu.
Ten typ zapytania może być wykonywany przez wielu użytkowników w krótkich odstępach czasu, gdy wybierają oni różne grupy danych i porównują wykresy z każdego wyniku. Czasem frustracja może być odczekanie prawie 10 sekund na wykres lub arkusz kalkulacyjny.
Dane są odrzucane po 90 dniach. Można go zarchiwizować, ale obecnie nie jest to wymagane.
Mamy nadzieję, że te informacje pomogą bardziej odpowiednio pokazać, w jaki sposób dane są wykorzystywane po ich gromadzeniu i przechowywaniu.
źródło
Odpowiedzi:
Powinieneś pomyśleć o podzieleniu tabeli z ważnego powodu.
Wszystkie indeksy, które masz na gigantycznej tabeli, nawet tylko jeden indeks, mogą generować duże obciążenie procesora i dyskowe operacje wejścia / wyjścia tylko po to, aby wykonać konserwację indeksu podczas wykonywania operacji INSERT, UPDATE i DELETE.
Wcześniejszy post, 7 października 2011 r., Napisałem o tym , dlaczego podział tabel byłby wielką pomocą. Oto jeden fragment mojego poprzedniego postu:
Później możesz przeczytać cały mój post .
Aby przejść do sedna, musisz poszukać i dowiedzieć się, jakie dane są rzadko używane w tabeli 10 GB. Dane te należy umieścić w tabeli archiwum, która jest łatwo dostępna, jeśli potrzebujesz zapytań adhoc o charakterze historycznym. Migracja tego archiwum z 10 GB, a następnie
OPTIMIZE TABLE
tabeli 10 GB, może spowodować, że zestaw roboczy będzie szybciej uruchamiał SELECT, INSERT, UPDATE i DELETE. Nawet DDL działałby szybciej na zestawie roboczym 2 GB niż na stole 10 GB.AKTUALIZACJA 2012-02-24 16:19 EDT
Dwie kwestie do rozważenia
Oto dwa posty, które napisałem o tym, jak go używać:
Oto dodatkowy post, który napisałem na tabelach z dużą ilością kolumn
Zbyt wiele kolumn w MySQL
źródło
Interesujące ... Jeśli wszystkie czujniki generują ten sam rodzaj danych, sensowne jest umieszczenie ich wszystkich w tej samej tabeli, ale przy takiej ilości danych widzę, dlaczego martwisz się o wydajność.
Czy 90 dni to zazwyczaj czas, przez który tworzony jest wykres? Jeśli tak, możesz mieć dwie tabele: główną tabelę danych czujnika, która przechowuje dane z 90 (lub nieco więcej, jeśli chcesz mieć luz) dni temu do dziś, i wszystko starsze niż to idzie w tabeli archiwum. Może to pomóc zmniejszyć rozmiar tabeli, z której generowane są raporty, i mam nadzieję, że większość 10 GB danych będzie w tabeli archiwum, a nie w głównej tabeli. Zadanie archiwizacji można zaplanować na nocne uruchamianie.
Być może rozważ także zbudowanie oddzielnej bazy danych raportowania, która przechowuje dane w strukturze, która jest lepsza do generowania raportów (tabele zaprojektowane w celu ściślejszego dopasowania do zapytań, i może wstępnie obliczyć i agregować wartości, które w innym przypadku zajęłyby dużo czasu generuj, jeśli to możliwe) i wypełniaj je ponownie z głównej bazy danych regularnie (np. co noc). Oczywiście, jeśli potrzebujesz raportów generowanych na podstawie aktualnych danych, może to nie działać tak dobrze.
źródło