Optymalizacja przechowywania danych

0

Przechowuję obecnie dość dużą liczbe danych w MySQLu około 300000 nowych rekordów na godzine. Przy obecnie kilku milionach rekordów select trwa lekko poniżej sekundy, co nie jest zbyt zadowalających wynikiem. Mam parę pomysłow jak to zoptymalizować, lecz nie do końca wiem jak to zrealizować. Obecny schmat tabelii to mniej więcej coś takiego:
id, point1, point2, time
point1 i point2 to inty, które mogą się powtarzać i bardzo często to robią.
time trzyma czas w którym akcja zapisu do bazy danych miała miejsce.
Żeby zwrócić interesujący mnie wynik używam mniej więcej takiego query:

select id, point1, point2, time from table where point1 = 1 and point2 = 1 order by time desc limit 25;

Tu już pojawią się 2 możliwości optymalizacji, nie potrzebuje trzymać, więcej niż 25 elementów z danymi punktami i nie potrzebuje też starszych niż np. dzień.
Dlatego najlepiej byłoby po prostu te informacje z bazy danych usuwać.
Zastanawiałem się też nad jakimś podzieleniem tych informacji, te punkty należą zawsze do jakiegoś regionu i dla tego danego regionu mogłoby być 200 razy mniej elementów do przeszukania.
Tylko nie wiem czy w mysqlu jest możliwość zrobienia coś własnie w rodzaju tych grup.
Oprócz optymalizacji aplikacji pod obecną bazę danych myślałem też nad jej zmianą, wydaje mi się, że mysql nie jest odpowiednią bazą do przechowywania takiej ilości takich informacji. Czy w tej sytuacji wybranie np. Cassandry nie byłoby dużo lepszym rozwiązaniem?

1
  1. co to ma wspólnego z Javą?
  2. Milczysz o indeksach (a czas odczytu jest ważny)
  3. Wybór bazy .... to zależy, np. masz plan/możliwość rozwijać ilość maszyn pod bazą danych, czy nie?
  4. Taka dobowa ilośc danych, to ile? Jakieś in-gridy? Wyboru baz NoSQL (o ile) to należy dokonywać wg celów, a nie wg mody...
1
sidav98 napisał(a):

Przechowuję obecnie dość dużą liczbe danych w MySQLu około 300000 nowych rekordów na godzine. Przy obecnie kilku milionach rekordów select trwa lekko poniżej sekundy, co nie jest zbyt zadowalających wynikiem. Mam parę pomysłow jak to zoptymalizować, lecz nie do końca wiem jak to zrealizować. Obecny schmat tabelii to mniej więcej coś takiego:
id, point1, point2, time
point1 i point2 to inty, które mogą się powtarzać i bardzo często to robią.
time trzyma czas w którym akcja zapisu do bazy danych miała miejsce.
Żeby zwrócić interesujący mnie wynik używam mniej więcej takiego query:

select id, point1, point2, time from table where point1 = 1 and point2 = 1 order by time desc limit 25;

Tu już pojawią się 2 możliwości optymalizacji, nie potrzebuje trzymać, więcej niż 25 elementów z danymi punktami i nie potrzebuje też starszych niż np. dzień.
Dlatego najlepiej byłoby po prostu te informacje z bazy danych usuwać.
Zastanawiałem się też nad jakimś podzieleniem tych informacji, te punkty należą zawsze do jakiegoś regionu i dla tego danego regionu mogłoby być 200 razy mniej elementów do przeszukania.
Tylko nie wiem czy w mysqlu jest możliwość zrobienia coś własnie w rodzaju tych grup.
Oprócz optymalizacji aplikacji pod obecną bazę danych myślałem też nad jej zmianą, wydaje mi się, że mysql nie jest odpowiednią bazą do przechowywania takiej ilości takich informacji. Czy w tej sytuacji wybranie np. Cassandry nie byłoby dużo lepszym rozwiązaniem?

Przede wszystkim powiedz czy masz indeksy na kolumnie point1 i point2? Jeżeli nie to koniecznie załóż. Jeżeli wyszukujesz tylko dane z ostatniego dnia to albo:

  1. Usuwaj stare dane procedurą lub jakimś skryptem zwykły cron + prosty kawałek kodu.
    2.a Dodaj do zapytania warunek na dzień np.
select id, point1, point2, time from table where point1 = 1 and point2 = 1 and time > sysdate-1 order by time desc limit 25;

2.b W takim razie dodaj też index na kolumnę time

Powyższe na pewno pomoże.

0

A ja bym przekornie spytał: potrzebujesz w ogóle trzymać to w bazie? Ja bym trzymał w pamięci tylko te interesujace cie dane, a serializował do bazy stan tylko raz na jakiś czas jeśli koniecznie chcesz mieć persystentne.

1

Skoro i tak je chcesz usuwać, a zależy Ci na szybkości to może zaprzyjaźnij się z Redisem? A tak to co? Możesz popartycjonować bazę danych (po wcześniejszym pogrupowaniu, bo mówiłeś, że myślisz o dodaniu regionu), spróbować zoptymalizować rodzaje zapisywanych danych, dodać indeksy gdzie się da, no i druga kwestia jeśli masz dostęp do serwera przydzielić więcej pamięci na cache w /etc/mysql/my.cnf (jest sporo tutoriali pokazujących jak to stuningować). Ja bym też spróbował postawić to na MariaDB lub PostgreSQL.

0
Shalom napisał(a):

A ja bym przekornie spytał: potrzebujesz w ogóle trzymać to w bazie? Ja bym trzymał w pamięci tylko te interesujace cie dane, a serializował do bazy stan tylko raz na jakiś czas jeśli koniecznie chcesz mieć persystentne.

Raczej nie widze sensu trzymać tego w ramie, dużo jest tych informacji, ale tak naprawdę mało z nich jest używane i niezbyt często, ale muszą być przechowywane, żeby były dokładne.
A po dodaniu indeksu przy 3 milionach elementów czas odpowiedzi to 10 ms.

2

Nie bardzo rozumiem. Skoro chcesz tylko 25 ostatnich to nie ma potrzeby trzymać innych chyba ze czegoś nie rozumiem. Poza tym chcesz optymalizować czas, a to robi się właśnie trzymając dane w pamięci...

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.