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

Jak przyspieszyć wybór liczenia(*) z grupowaniem według i gdzie?

Oto kilka rzeczy, które chciałbym wypróbować, w kolejności rosnącej trudności:

(łatwiej) - Upewnij się, że masz odpowiedni indeks pokrycia

CREATE INDEX ix_temp ON relations (relation_title, object_title);

Powinno to zmaksymalizować wydajność biorąc pod uwagę istniejący schemat, ponieważ (chyba że twoja wersja optymalizatora mySQL jest naprawdę głupia!) zminimalizuje to ilość operacji we/wy potrzebnych do spełnienia zapytania (w przeciwieństwie do indeksu w odwrotnej kolejności gdzie cały indeks musi zostać zeskanowany) i obejmie zapytanie, więc nie będziesz musiał dotykać indeksu klastrowego.

(trochę trudniej) – upewnij się, że pola Varchar są jak najmniejsze

Jednym z problemów wydajnościowych z indeksami varchar w MySQL jest to, że podczas przetwarzania zapytania do pamięci RAM zostanie przeniesiony pełny zadeklarowany rozmiar pola. Więc jeśli masz varchar(256), ale używasz tylko 4 znaków, nadal płacisz za 256-bajtowe użycie pamięci RAM podczas przetwarzania zapytania. Auć! Jeśli więc możesz łatwo zmniejszyć limity varcharów, powinno to przyspieszyć Twoje zapytania.

(mocniej) – Normalizuj

30% twoich wierszy z pojedynczą wartością ciągu to wyraźny wołanie o normalizację do innej tabeli, aby nie duplikować ciągów miliony razy. Rozważ znormalizowanie do trzech tabel i dołączanie do nich identyfikatorów całkowitych.

W niektórych przypadkach możesz znormalizować pod okładkami i ukryć normalizację z widokami, które pasują do nazwy aktualnej tabeli... wtedy wystarczy, że twoje zapytania INSERT/UPDATE/DELETE będą świadome normalizacji, ale możesz zostawić swoje SELECTy w spokoju .

(najtrudniejsze) – Zahaszuj kolumny ciągów i indeksuj skróty

Jeśli normalizacja oznacza zmianę zbyt dużej ilości kodu, ale możesz trochę zmienić swój schemat, możesz rozważyć utworzenie 128-bitowych skrótów dla kolumn z ciągami (używając funkcja MD5 ). W tym przypadku (w przeciwieństwie do normalizacji) nie musisz zmieniać wszystkich zapytań, tylko INSERT i niektóre SELECTy. W każdym razie będziesz chciał zahaszować swoje pola tekstowe, a następnie utworzyć indeks na hashach, np.

CREATE INDEX ix_temp ON relations (relation_title_hash, object_title_hash);

Zwróć uwagę, że będziesz musiał pobawić się SELECT, aby upewnić się, że wykonujesz obliczenia za pomocą indeksu mieszającego i nie pobierasz indeksu klastrowego (wymagane do rozwiązania rzeczywistej wartości tekstowej object_title w celu spełnienia zapytania).

Ponadto, jeśli relations_title ma mały rozmiar varchar, ale tytuł obiektu ma długi rozmiar, możesz potencjalnie zahaszować tylko object_title i utworzyć indeks na (relation_title, object_title_hash) .

Zauważ, że to rozwiązanie pomaga tylko wtedy, gdy jedno lub oba z tych pól są bardzo długie w stosunku do rozmiaru skrótów.

Należy również zauważyć, że hash ma interesujące skutki rozróżniania wielkości liter/porównywania, ponieważ hash ciągu pisanego małymi literami nie jest tym samym, co hash ciągu pisanego wielkimi literami. Musisz więc upewnić się, że zastosowałeś kanonizację do łańcuchów przed ich haszowaniem — innymi słowy, haszuj tylko małe litery, jeśli jesteś w bazie danych bez rozróżniania wielkości liter. Możesz również chcieć przycinać spacje od początku lub końca, w zależności od tego, jak DB obsługuje spacje wiodące/końcowe.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak uzyskać dostęp do zdalnego serwera za pomocą lokalnego klienta phpMyAdmin?

  2. Odrębne zapytanie Django MySQL w celu uzyskania wielu wartości

  3. Technika czystego SQL dla automatycznego numerowania wierszy w zestawie wyników

  4. Jak znaleźć sortowanie w MySQL

  5. Do czego służy katalog adnotacji @Table JPA i zmienne schematu?