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.