Optymalizator zapytań

Komponent bazy wybierający najefektywniejszy sposób wykonania zapytania. Decyduje m.in. o użyciu indeksów i kolejności złączeń.

Optymalizator zapytań (ang. query optimizer) to komponent silnika bazy danych, który dla pojedynczego zapytania SQL wybiera najefektywniejszy sposób jego wykonania. Ty piszesz co chcesz dostać (np. SELECT ... JOIN ... WHERE), a optymalizator decyduje jak to policzyć: czy skanować całą tabelę, czy sięgnąć po indeks, w jakiej kolejności łączyć tabele i jaki algorytm złączenia zastosować. Efektem jego pracy jest tzw. plan wykonania (execution plan).

Jak to działa

Dla jednego zapytania istnieje zwykle wiele równoważnych planów dających ten sam wynik, ale różniących się czasem i zużyciem zasobów o rzędy wielkości. Większość nowoczesnych baz (PostgreSQL, MySQL, Oracle, SQL Server) używa optymalizatora kosztowego (cost-based): na podstawie statystyk o danych — liczby wierszy, rozkładu wartości w kolumnach, rozmiaru tabel — szacuje koszt każdego kandydata i wybiera ten o najniższym koszcie. Koszt to nie sekundy, tylko umowna jednostka łącząca operacje I/O i CPU.

Dlatego aktualne statystyki są kluczowe. Jeśli baza myśli, że tabela ma 100 wierszy, a ma ich 10 milionów, wybierze plan idealny dla 100 wierszy — i Twoje zapytanie będzie się wlokło. Stąd polecenia w stylu ANALYZE (Postgres) czy ANALYZE TABLE (MySQL), które odświeżają te dane.

Przykład z praktyki

W PostgreSQL podejrzysz decyzje optymalizatora komendą EXPLAIN. Sam EXPLAIN SELECT * FROM zamowienia WHERE klient_id = 42; pokaże planowany plan bez uruchamiania zapytania. Dorzuć ANALYZEEXPLAIN ANALYZE ... — a baza faktycznie wykona zapytanie i pokaże szacunki obok realnych czasów i liczby wierszy. Jeśli zobaczysz Seq Scan (skan całej tabeli) tam, gdzie spodziewasz się Index Scan, to częsty sygnał: brakuje indeksu albo statystyki są nieaktualne.

Częste błędy i mity

  • „Dodam indeks i będzie szybciej.” Nie zawsze. Przy zapytaniu zwracającym dużą część tabeli optymalizator i tak wybierze skan sekwencyjny, bo to tańsze niż tysiące skoków po indeksie.
  • Zmuszanie planu na siłę. Niektóre bazy pozwalają na tzw. hinty (w Postgresie przez rozszerzenie pg_hint_plan, np. IndexScan czy Leading dla kolejności złączeń). Społeczność PostgreSQL zaleca to traktować jako ostateczność i narzędzie do debugowania — zwykle lepiej naprawić statystyki niż obchodzić optymalizator.
  • Ignorowanie nieaktualnych statystyk to najczęstsza przyczyna nagłego spadku wydajności po dużym imporcie danych.

Pojęcia powiązane: plan wykonania (execution plan), indeks, EXPLAIN/EXPLAIN ANALYZE, koszt zapytania, statystyki tabeli, kolejność złączeń (join order), skan sekwencyjny i indeksowy.