[ Pobierz całość w formacie PDF ]
.Taka funkcja jest oferowana przez niektóre serwery baz danych, ale nie przezMySQL.Autorzy wspominają, aby nie poświęcać zbyt dużej ilości czasu na próbę odkrycia,jak w MySQL uzyskać wykonywanie zapytania równocześnie na wielu procesorach.Złączenia typu hashPodczas pisania książki baza danych MySQL nie przeprowadzała prawdziwych złączeń typuhash wszystko pozostaje złączeniem w postaci zagnieżdżonej pętli.Jednak złączenia typuhash można emulować za pomocą indeksów typu hash.Jeżeli używany silnik magazynu da-nych jest inny niż Memory, trzeba także emulować indeksy typu hash.Więcej informacjina ten temat przedstawiono w sekcji Budowa własnych indeksów typu hash , znajdującejsię w rozdziale 3.Luzne skanowanie indeksuBaza danych MySQL znana jest z tego, że nie umożliwia przeprowadzenia luznego skano-wania indeksu, które polega na skanowaniu nieprzylegających do siebie zakresów indeksu.Ogólnie rzecz biorąc, skanowanie indeksu w MySQL wymaga zdefiniowania punktu począt-kowego oraz końcowego w indeksie nawet wtedy, jeśli kilka nieprzylegających do siebierekordów w środku jest naprawdę pożądanych w danym zapytaniu.Baza danych MySQLbędzie skanowała cały zakres rekordów wewnątrz zdefiniowanych punktów końcowych.Przykład pomoże w zilustrowaniu tego problemu.Zakładamy, że tabela zawiera indeksobejmujący kolumny (a, b), a programista chce wykonać poniższe zapytanie:mysql> SELECT.FROM tbl WHERE b BETWEEN 2 AND 3;Ponieważ indeks rozpoczyna się od kolumny a, ale klauzula WHERE zapytania nie zawierakolumny a, baza danych MySQL przeprowadzi skanowanie tabeli oraz za pomocą klauzuliWHERE wyeliminuje nieprzylegające do siebie rekordy, co pokazano na rysunku 4.5.Bardzo łatwo można dostrzec, że istnieją szybsze sposoby wykonania tego zapytania.Strukturaindeksu (ale nie API silnika magazynu danych MySQL) pozwala na wyszukanie początkukażdego zakresu wartości, skanowanie aż do końca zakresu, a następnie przejście na początekkolejnego zakresu.Na rysunku 4.6 pokazano, jak taka strategia mogłaby wyglądać, gdybyzostała zaimplementowana w MySQL.204 | Rozdział 4.Optymalizacja wydajności zapytańRysunek 4.5.Baza danych MySQL skanuje całą tabelę w celu wyszukania rekordówRysunek 4.6.Luzne skanowanie indeksu, którego MySQL aktualnie nie wykonuje, byłoby efektywniejszymsposobem wykonania omawianego zapytaniaOgraniczenia optymalizatora zapytań MySQL | 205Warto zwrócić uwagę na brak klauzuli WHERE, która stała się zbędna, ponieważ sam indekspozwala na pomijanie niepotrzebnych rekordów.(Przypominamy ponownie, że baza danychMySQL nie ma jeszcze takich możliwości).Jest to, co prawda, uproszczony przykład i przedstawione zapytanie można łatwo zoptyma-lizować poprzez dodanie innego indeksu.Jednak istnieje wiele sytuacji, gdy dodanie innegoindeksu nie stanowi rozwiązania.Jednym z takich przypadków jest zapytanie, które zawierawarunek zakresu względem pierwszej kolumny indeksu oraz warunek równości względemdrugiej kolumny indeksu.Począwszy od MySQL w wersji 5.0, operacja luznego skanowania indeksu jest możliwa w pew-nych ściśle określonych sytuacjach, np.w zapytaniach wyszukujących wartości maksymalnąi minimalną w zgrupowanym zapytaniu:mysql> EXPLAIN SELECT actor_id, MAX(film_id)-> FROM sakila.film_actor-> GROUP BY actor_id\G*************************** Rekord 1.***************************id: 1select_type: SIMPLEtable: film_actortype: rangepossible_keys: NULLkey: PRIMARYkey_len: 2ref: NULLrows: 396Extra: Using index for group-byInformacja Using index for group-by wyświetlona w danych wyjściowych polecenia EXPLAINwskazuje na zastosowanie luznego skanowania indeksu.To jest dobry rodzaj optymalizacjiw tym specjalnym przypadku, ale równocześnie nie jest to ogólnego przeznaczenia luzneskanowanie indeksu.Lepiej byłoby, gdyby informacja miała postać loose index probe.Dopóki baza danych MySQL nie będzie obsługiwała ogólnego przeznaczenia luznego ska-nowania indeksu, obejściem problemu jest zastosowanie stałej bądz listy stałych dla pierw-szych kolumn indeksu.W zaprezentowanym w poprzednim rozdziale studium przypadkuindeksowania przedstawiono kilka przykładów osiągnięcia dobrej wydajności za pomocą takichzapytań.Funkcje MIN() i MAX()Baza danych MySQL nie może zbyt dobrze zoptymalizować pewnych zapytań wykorzystu-jących funkcje MIN() lub MAX().Oto przykład takiego zapytania:mysql> SELECT MIN(actor_id) FROM sakila.actor WHERE first_name = 'PENELOPE';Ponieważ nie ma indeksu obejmującego kolumnę first_name, powyższe zapytanie spowodujeprzeprowadzenie skanowania tabeli.Jeżeli MySQL skanuje klucz podstawowy, teoretyczniemoże zatrzymać skanowanie po odczytaniu pierwszego dopasowanego rekordu, gdyż kluczpodstawowy jest w kolejności ściśle rosnącej i każdy następny rekord będzie miał większąwartość actor_id.Jednak w omawianym przypadku MySQL przeskanuje całą tabelę, o czymmożna się przekonać po sprofilowaniu zapytania.Rozwiązaniem problemu jest usunięciefunkcji MIN() i napisanie zapytania z użyciem klauzuli LIMIT, np.następująco:mysql> SELECT actor_id FROM sakila.actor USE INDEX(PRIMARY)-> WHERE first_name = 'PENELOPE' LIMIT 1;206 | Rozdział 4.Optymalizacja wydajności zapytańTaka strategia bardzo często działa doskonale w innej sytuacji, kiedy baza danych MySQLwybrała skanowanie większej liczby rekordów niż potrzeba.Puryści mogą uznać, że tegorodzaju zapytanie oznacza brak zrozumienia SQL.Z reguły programista informuje serwer,co chce uzyskać, a serwer określa, jak pobrać te dane.W omawianym zapytaniu programistainformuje serwer MySQL, jak wykonać dane zapytanie
[ Pobierz całość w formacie PDF ]