0Pricing
Coding Interview Prep · Lekcja

Odczytywanie planu EXPLAIN

Interpretowanie typów skanowania, metod złączeń i szacunków kosztów w planie zapytania.

Odczytywanie planu EXPLAIN to bezpłatna lekcja Coding Interview Prep na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Coding Interview Prep, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Coding Interview Prep zawiera 4 lekcji w sumie.

Dlaczego rekrutujący pytają o EXPLAIN

Gdy rozmowa rekrutacyjna dotyczy stanowiska seniorskiego, rekrutujący przestają pytać jak napisać zapytanie, a zaczynają pytać dlaczego to zapytanie działa wolno. Narzędziem, które pozwala na to odpowiedzieć, jest EXPLAIN.

EXPLAIN pokazuje plan wykonania bazy danych: krok po kroku strategię, którą optymalizator wybrał do uruchomienia zapytania SQL. Ujawnia, które tabele są skanowane, w jakiej kolejności są łączone oraz jaki jest przybliżony koszt każdego kroku.

Umiejętność odczytywania planu pokazuje, że rozumie Pan/Pani działanie silnika, a nie tylko składnię. Właśnie to pozwala rekrutującym odróżnić poziom średniozaawansowany od seniorskiego.

EXPLAIN a EXPLAIN ANALYZE

Istnieją dwa warianty i rekrutujący bardzo cenią znajomość tej różnicy.

  • EXPLAIN pokazuje szacowany plan optymalizatora bez uruchamiania zapytania. Jest szybki i bezpieczny.
  • EXPLAIN ANALYZE rzeczywiście wykonuje zapytanie i obok wartości szacowanych podaje rzeczywiste liczby wierszy oraz czasy wykonania.

Najcenniejsze jest porównanie szacowanej liczby wierszy z rzeczywistą. Duża rozbieżność oznacza, że optymalizator dysponuje nieprawidłowymi statystykami i prawdopodobnie podejmuje złą decyzję.

Uwaga: EXPLAIN ANALYZE rzeczywiście uruchamia zapytanie, więc wykona ono każde polecenie INSERT lub UPDATE, chyba że zostanie opakowane w transakcję, która jest następnie wycofywana.

EXPLAIN ANALYZE
SELECT * FROM orders WHERE customer_id = 42;

Jak czytać drzewo

Plan jest drzewem, a nie listą. Najbardziej wcięte węzły to liście, które są wykonywane jako pierwsze; wyniki przepływają w górę do korzenia, który tworzy ostateczny rezultat.

Plan należy czytać od środka na zewnątrz: trzeba znaleźć najgłębszy węzeł, ponieważ właśnie tam rozpoczyna się wykonanie. Każdy węzeł nadrzędny przetwarza wiersze zwrócone przez swoje węzły podrzędne.

Podczas rozmowy należy opisywać to w ten sposób: najpierw skanujemy tę tabelę, te wiersze trafiają do tego złączenia, złączenie przekazuje wynik do sortowania, a sortowanie do limitu. Właśnie takiego opisu od dołu do góry oczekują rekrutujący.

Anatomia węzła planu

Każdy węzeł planu Postgres zawiera te same kluczowe liczby:

  • cost=0.00..35.50 koszt uruchomienia..koszt całkowity w arbitralnych jednostkach planisty
  • rows=1000 szacowana liczba zwróconych wierszy
  • width=64 szacowany średni rozmiar wiersza w bajtach

Pierwszy koszt to koszt uruchomienia (praca wykonywana przed pojawieniem się pierwszego wiersza, na przykład zbudowanie tablicy haszującej). Drugi to koszt całkowity zwrócenia wszystkich wierszy. Wyższy koszt całkowity oznacza, że planista przewiduje większy względny koszt.

Seq Scan on orders  (cost=0.00..35.50 rows=1000 width=64)

Przykład z omówieniem

Rozważmy proste zapytanie z filtrem. Poniższy plan przedstawia całą sytuację w jednym wierszu.

Jest to Seq Scan (odczyt całej tabeli) na orders, z zastosowaniem filtra status = 'shipped'. Planista szacuje, że pasuje 1000 wierszy.

Jeśli tabela orders ma 10 milionów wierszy, a pasuje tylko 1000 z nich, na rozmowie rekrutacyjnej należy powiedzieć: skanowanie sekwencyjne jest tutaj nieefektywne, a indeks na kolumnie status (lub na kolumnie o większej selektywności) pozwoliłby uniknąć odczytywania całej tabeli.

EXPLAIN SELECT * FROM orders WHERE status = 'shipped';

Seq Scan on orders  (cost=0.00..18334.00 rows=1000 width=64)
  Filter: (status = 'shipped'::text)

Szacowana a rzeczywista liczba wierszy

Za pomocą EXPLAIN ANALYZE otrzymuje się również rzeczywiste liczby w nawiasach.

Spójrzmy na przykład: planista oszacował 1000 wierszy, ale rzeczywiście otrzymał ich 480000. To 480-krotne niedoszacowanie. Planista wybrał strategię, zakładając niewielką liczbę wierszy, więc jego wybór prawdopodobnie nie pasuje do rzeczywistych danych.

Na rozmowie rekrutacyjnej ta rozbieżność jest najważniejszą diagnozą: statystyki są nieaktualne, należy uruchomić ANALYZE dla tabeli, a wtedy planista prawdopodobnie wybierze lepszy plan.

Seq Scan on orders
  (cost=0.00..18334.00 rows=1000 width=64)
  (actual time=0.02..210.4 rows=480000 loops=1)

Co oznacza loops=N

Wartość loops ma większe znaczenie, niż oczekuje wielu kandydatów. Oznacza liczbę wykonań danego węzła.

Wartość ta pojawia się po wewnętrznej stronie złączenia Nested Loop: wewnętrzny węzeł jest uruchamiany dla każdego wiersza zewnętrznego. Jeśli loops=480000, ten wewnętrzny krok wykonał się 480 tysięcy razy.

Ważne: pokazany czas i liczba wierszy są wartościami dla jednej iteracji. Aby uzyskać prawdziwą wartość całkowitą, należy pomnożyć je przez loops. Węzeł, który wygląda na tani przy wartości 0.004ms na iterację, przy 480000 iteracjach zajmuje prawie 2 sekundy.

Index Scan using idx_cust on orders
  (actual time=0.003..0.004 rows=1 loops=480000)

Koszt jest względny, a nie wyrażony w milisekundach

Częsta pułapka: kandydaci widzą cost=18334 i mówią to trwa 18 sekund. To błąd.

Koszt jest wyrażony w arbitralnych jednostkach planisty, skalibrowanych tak, aby jeden sekwencyjny odczyt strony odpowiadał wartości 1.0. Ma znaczenie wyłącznie przy porównywaniu planów między sobą, a nie jako wartość czasu rzeczywistego.

Do pomiaru rzeczywistego czasu potrzebne są EXPLAIN ANALYZE i wartości actual time, podawane w milisekundach. Należy wyraźnie powiedzieć to na rozmowie rekrutacyjnej — pokazuje to rzeczywiste zrozumienie tej metryki.

Czytanie planu złączenia

Oto plan dla dwóch tabel. Należy czytać go od dołu do góry.

Dwa pierwsze skany pobierają wiersze z orders i customers. Przekazują je do Hash Join: jedna strona jest haszowana, a druga wyszukuje dane w tablicy haszującej. Wynik złączenia jest następnie przekazywany do końcowego wyniku.

Zwróć uwagę, że wcięcia pokazują strukturę: oba skany znajdują się pod Hash Join. Rekruter oczekuje wskazania metody złączenia (tutaj haszowanie) oraz tabeli, dla której tworzona jest tablica haszująca (zwykle mniejszej).

Hash Join  (cost=30.0..520.0 rows=900 width=72)
  Hash Cond: (o.customer_id = c.id)
  ->  Seq Scan on orders o  (cost=0..400 rows=10000)
  ->  Hash  (cost=18..18 rows=500)
        ->  Seq Scan on customers c  (cost=0..18 rows=500)

Sygnały ostrzegawcze, które należy wskazać

Wyrób sobie nawyk dostrzegania tych sygnałów ostrzegawczych w każdym planie:

  • Seq Scan na dużej tabeli z selektywnym filtrem — indeks może pomóc.
  • Szacowana liczba wierszy znacznie różni się od rzeczywistej — statystyki są nieaktualne.
  • Nested Loop z dużą wartością loops na dużej tabeli — często oznacza brak indeksu na wewnętrznym kluczu złączenia.
  • Sort lub Hash zapisuje dane na dysku (pokazane jako użycie Disk) — work_mem jest zbyt małe.
  • Rows Removed by Filter ma bardzo wysoką wartość — odczytano i odrzucono większość tabeli.

Formaty wyjściowe i BUFFERS

Plany są dostępne w kilku formatach. Domyślny format TEXT to ten, który odczytuje się na głos podczas rozmów rekrutacyjnych. Można jednak również zażądać ustrukturyzowanego wyniku.

EXPLAIN (FORMAT JSON) lub FORMAT YAML tworzy plany czytelne maszynowo, które mogą analizować narzędzia i panele. Rzadko trzeba czytać je ręcznie, ale świadomość ich istnienia to dobry szczegół świadczący o dużym doświadczeniu.

Opcje dodaje się w nawiasach: EXPLAIN (ANALYZE, BUFFERS). Opcja BUFFERS pokazuje trafienia w pamięci podręcznej oraz odczyty z dysku, co jest niezwykle przydatne przy diagnozowaniu zapytań ograniczonych przez operacje wejścia-wyjścia.

EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM orders WHERE customer_id = 42;

Szybkie sprawdzenie

Rekruter pokazuje węzeł EXPLAIN ANALYZE, w którym w sekcji kosztu widnieje rows=1000, ale actual ... rows=480000. Jaka jest najbardziej prawdopodobna diagnoza?

Podsumowanie

Można już czytać plan jak doświadczony specjalista:

  • EXPLAIN wykonuje szacunki, a EXPLAIN ANALYZE uruchamia plan i dokonuje pomiarów.
  • Drzewo należy czytać od dołu do góry; liście są wykonywane jako pierwsze, a korzeń tworzy wynik.
  • Każdy węzeł pokazuje koszt (jednostki względne), liczbę wierszy i szerokość; actual time to rzeczywista wartość w milisekundach.
  • loops mnoży wartości dla jednej iteracji, dlatego należy zwracać uwagę na zagnieżdżone pętle.
  • Rozbieżność między szacowaną a rzeczywistą liczbą wierszy jest najważniejszym sygnałem diagnostycznym.

Głośne omawianie planu i wskazywanie sygnałów ostrzegawczych to zachowanie, które robi najlepsze wrażenie na rozmowie rekrutacyjnej.

Często zadawane pytania

Czy lekcja „Odczytywanie planu EXPLAIN” jest bezpłatna?

Tak — pełny tekst „Odczytywanie planu EXPLAIN” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Coding Interview Prep, przejdź na CoddyKit PRO. Kurs Coding Interview Prep zawiera 4 lekcji w sumie.

Co nauczysz się w „Odczytywanie planu EXPLAIN”?

Interpretowanie typów skanowania, metod złączeń i szacunków kosztów w planie zapytania. Ćwiczysz Coding Interview Prep z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Coding Interview Prep?

Nie wymagamy żadnego doświadczenia. Coding Interview Prep w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.

Ile czasu zajmuje lekcja „Odczytywanie planu EXPLAIN”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Coding Interview Prep?

Tak. Każda lekcja Coding Interview Prep zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Odczytywanie planu EXPLAIN
  2. Seq Scan a Index Scan i Index-Only
  3. Algorytmy złączeń: Nested Loop, Hash, Merge
  4. Wykrywanie i naprawianie wolnych zapytań
← Powrót do Coding Interview Prep