Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Wydajność MySQL:wiele tabel a indeks na jednej tabeli i partycjach

Tworzenie 20 000 stołów to zły pomysł. Niedługo będziesz potrzebować 40 000 stołów, a nawet więcej.

Nazwałem ten syndrom Metadata Tribbles w mojej książce Antywzorce SQL . Widzisz, że dzieje się tak za każdym razem, gdy planujesz utworzyć „tabelę na X” lub „kolumnę na X”.

Powoduje to prawdziwe problemy z wydajnością, gdy masz dziesiątki tysięcy tabel. Każda tabela wymaga, aby MySQL utrzymywał wewnętrzne struktury danych, deskryptory plików, słownik danych itp.

Są też praktyczne konsekwencje operacyjne. Czy na pewno chcesz stworzyć system, który będzie wymagał tworzenia nowej tabeli za każdym razem, gdy rejestruje się nowy użytkownik?

Zamiast tego polecam użycie partycjonowania MySQL .

Oto przykład partycjonowania tabeli:

CREATE TABLE statistics (
  id INT AUTO_INCREMENT NOT NULL,
  user_id INT NOT NULL,
  PRIMARY KEY (id, user_id)
) PARTITION BY HASH(user_id) PARTITIONS 101;

Daje to korzyści w postaci zdefiniowania jednej tabeli logicznej, a także podzielenia tabeli na wiele tabel fizycznych w celu szybszego dostępu podczas zapytania o określoną wartość klucza partycji.

Na przykład, gdy uruchamiasz zapytanie takie jak w przykładzie, MySQL uzyskuje dostęp tylko do prawidłowej partycji zawierającej określony identyfikator użytkownika:

mysql> EXPLAIN PARTITIONS SELECT * FROM statistics WHERE user_id = 1\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: statistics
   partitions: p1    <--- this shows it touches only one partition 
         type: index
possible_keys: NULL
          key: PRIMARY
      key_len: 8
          ref: NULL
         rows: 2
        Extra: Using where; Using index

Metoda partycjonowania HASH oznacza, że ​​wiersze są umieszczane w partycji przez moduł klucza partycji typu integer. Oznacza to, że wiele identyfikatorów user_id jest mapowanych na tę samą partycję, ale każda partycja miałaby średnio tylko 1/N-tą liczbę wierszy (gdzie N to liczba partycji). I definiujesz tabelę ze stałą liczbą partycji, więc nie musisz jej rozszerzać za każdym razem, gdy masz nowego użytkownika.

Możesz wybrać dowolną liczbę partycji do 1024 (lub 8192 w MySQL 5.6), ale niektórzy ludzie zgłaszali problemy z wydajnością, gdy osiągają tak wysoki poziom.

Zaleca się stosowanie liczby pierwszej partycji. W przypadku, gdy wartości identyfikatora użytkownika są zgodne ze wzorcem (np. używanie tylko liczb parzystych), użycie liczby pierwszej partycji pomaga w bardziej równomiernym rozmieszczeniu danych.

Odpowiedz na swoje pytania w komentarzu:

W przypadku partycjonowania HASH, jeśli używasz 101 partycji, jak pokazano w powyższym przykładzie, to każda dana partycja ma średnio około 1% twoich wierszy. Powiedziałeś, że twoja tabela statystyk ma 30 milionów wierszy, więc jeśli użyjesz tego partycjonowania, będziesz mieć tylko 300 000 wierszy na partycję. To jest znacznie łatwiejsze do odczytania dla MySQL. Możesz (i powinieneś) również używać indeksów — każda partycja będzie miała swój własny indeks i będzie on tylko 1% tak duży, jak byłby indeks całej tabeli bez partycji.

Tak więc odpowiedź na pytanie, jak określić rozsądną liczbę partycji, brzmi:jak duży jest cały stół i jak duże mają być średnie partycje?

Liczba partycji niekoniecznie musi rosnąć, jeśli używasz partycjonowania HASH. W końcu możesz mieć łącznie 30 miliardów wierszy, ale odkryłem, że kiedy ilość danych rośnie o rzędy wielkości, i tak wymaga to nowej architektury. Jeśli Twoje dane będą tak duże, prawdopodobnie będziesz potrzebować shardingu na wielu serwerach, a także partycjonowanie na wiele tabel.

To powiedziawszy, możesz ponownie podzielić tabelę za pomocą ALTER TABLE:

ALTER TABLE statistics PARTITION BY HASH(user_id) PARTITIONS 401;

To musi zmienić strukturę tabeli (jak większość zmian ALTER TABLE), więc spodziewaj się, że zajmie to trochę czasu.

Możesz monitorować rozmiar danych i indeksów w partycjach:

SELECT table_schema, table_name, table_rows, data_length, index_length
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE partition_method IS NOT NULL;

Podobnie jak w przypadku każdej tabeli, chcesz, aby całkowity rozmiar aktywnych indeksów zmieścił się w Twojej puli buforów, ponieważ jeśli MySQL musi wymieniać części indeksów do i z puli buforów podczas zapytań SELECT, ucierpi wydajność.

Jeśli używasz partycjonowania RANGE lub LIST, dodawanie, usuwanie, łączenie i dzielenie partycji jest znacznie bardziej powszechne. Zobacz http://dev.mysql. com/doc/refman/5.6/en/partitioning-management-range-list.html

Zachęcam do przeczytania sekcji podręcznika na temat partycjonowania , a także obejrzyj tę ładną prezentację:Zwiększ wydajność Z partycjami MySQL 5.1 .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PHP - Uwaga:Niezdefiniowany indeks:

  2. Tworzenie kolumny sumy skumulowanej w MySQL

  3. INSERT IGNORE vs INSERT ... NA ZDUPLIKOWANY KLUCZ AKTUALIZACJI

  4. Ile wierszy zostanie zablokowanych przez WYBIERZ... ZAMÓW WEDŁUG xxx LIMIT 1 DO AKTUALIZACJI?

  5. Jak generować wykresy i wykresy z bazy danych mysql w php