Wiersz „Ponownie sprawdź Cond:” w planach zapytań ze skanowaniem indeksu bitmap

21

Jest to efekt uboczny komentarzy od poprzedniego pytania:

Używając PostgreSQL 9.4, Recheck Cond:po skanach indeksu bitmap zawsze pojawia się linia w wynikowych planach zapytań EXPLAIN.

Podobnie jak w EXPLAINwynikach odnośnego pytania:

->  Bitmap Heap Scan on table_three  (cost=2446.92..19686.74 rows=8159 width=7)
      Recheck Cond: (("timestamp" > (now() - '30 days'::interval)) AND (client_id > 0))
      ->  BitmapAnd  (cost=2446.92..2446.92 rows=8159 width=0)
            ->  Bitmap Index Scan on table_one_timestamp_idx  (cost=0.00..1040.00 rows=79941 width=0)
                  Index Cond: ("timestamp" > (now() - '30 days'::interval))
            ->  Bitmap Index Scan on fki_table_three_client_id  (cost=0.00..1406.05 rows=107978 width=0)
                  Index Cond: (client_id > 0)

Lub w wyniku EXPLAIN ANALYZEdla prostej, ogromnej tabeli (z bardzo małą ilością work_mem):

EXPLAIN ANALYZE SELECT * FROM aa WHERE a BETWEEN 100000 AND 200000;
Bitmap Heap Scan on aa  (cost=107.68..4818.05 rows=5000 width=4) (actual time=27.629..213.606 rows=100001 loops=1)
  Recheck Cond: ((a >= 100000) AND (a <= 200000))
  Rows Removed by Index Recheck: 758222
  Heap Blocks: exact=693 lossy=3732
  ->  Bitmap Index Scan on aai  (cost=0.00..106.43 rows=5000 width=0) (actual time=27.265..27.265 rows=100001 loops=1)
        Index Cond: ((a >= 100000) AND (a <= 200000))

Czy to oznacza, że ​​warunki indeksu należy sprawdzić po raz drugi po skanowaniu indeksu bitmapy?
Czego jeszcze możemy się nauczyć z EXPLAINwyników?

Erwin Brandstetter
źródło

Odpowiedzi:

17

Jak @Chris poprawnie skomentował przywoływane pytanie :

małe dochodzenie wydaje się wskazywać, że warunek ponownego sprawdzenia jest zawsze drukowany w EXPLAIN, ale w rzeczywistości jest wykonywany tylko wtedy, gdy work_memjest wystarczająco mały, aby bitmapa stała się stratna. Myśli? http://www.postgresql.org/message-id/[email protected]

Chociaż to wszystko prawda, a główny programista Heikki Linnakangas jest źródłem pierwszej klasy, post pochodzi z 2007 roku (Postgres 8.2). Oto post na blogu autorstwa Michaela Paquiera ze szczegółowym wyjaśnieniem Postgres 9.4 , w którym wyniki EXPLAIN ANALYZEzostały ulepszone o więcej informacji.

Recheck Cond:Linia jest zawsze tam dla skanów indeksów bitmapy. Wydajność podstawowego EXPLAINnie powie nam więcej. Otrzymujemy dodatkowe informacje z EXPLAIN ANALYZEdrugiego cytatu w pytaniu:

Heap Blocks: exact=693 lossy=3732

Z łącznej liczby 4425 stron danych (bloków) 693 dokładnie zapisało krotki (w tym wskaźniki krotek), podczas gdy pozostałe 3732 strony były stratne (tylko strona danych) w mapie bitowej. Dzieje się tak, gdy work_memnie jest wystarczająco duży, aby zapisać dokładnie całą mapę bitową zbudowaną ze skanowania indeksu (bezstratnie).

Warunek indeksu należy ponownie sprawdzić pod kątem stron z udziału stratnego, ponieważ mapa bitowa pamięta tylko, które strony mają zostać pobrane, a nie dokładne krotki na stronie. Nie wszystkie krotki na stronie muszą przechodzić warunki indeksu, konieczne jest faktycznie ponownie sprawdzić stan.

Jest to wątek na temat hakerów pgsql, w których omawiano nowy dodatek . Autor Etsuro Fujita zapewnia formułę obliczania minimum, work_memaby uniknąć stratnych wpisów bitmapy i ponownych sprawdzeń warunków. Obliczenia nie są wiarygodne dla złożonych przypadków z wieloma skanami bitmapowymi, więc nie zostały użyte do wyprowadzenia rzeczywistych liczb EXPLAIN. Nadal może służyć jako oszacowanie dla prostych przypadków.

Dodatkowa linia BUFFERS:

Ponadto, gdy działa z BUFFERSopcją: EXPLAIN (ANALYZE, BUFFERS) ...dodawany jest inny wiersz, np .:

Buffers: shared hit=279 read=79

Wskazuje to, ile bazowej tabeli (i indeksu) odczytano z pamięci podręcznej ( shared hit=279) i ile trzeba było pobrać z disk ( read=79). Jeśli powtórzysz zapytanie, część „czytaj” zwykle znika dla niezbyt dużych zapytań, ponieważ wszystko jest buforowane teraz po pierwszym wywołaniu. Pierwsze połączenie informuje, ile już zostało buforowane. Kolejne wywołania pokazują, ile pamięć podręczna może obsłużyć (obecnie).

Jest więcej opcji. Podręcznik na temat BUFFERSopcji:

W szczególności obejmują liczbę trafionych, odczytanych, zabrudzonych i zapisanych bloków współdzielonych, liczbę trafionych, odczytanych, zabrudzonych i zapisanych bloków lokalnych oraz liczbę odczytanych i zapisanych bloków tymczasowych.

Czytaj dalej, jest więcej.
Oto lista opcji wyjściowych w kodzie źródłowym .

Erwin Brandstetter
źródło
10

Erwin, ponieważ była to nasza dyskusja w wątku komentarza z wcześniej, postanowiłem pogłaskać ją trochę dalej ...

Mam bardzo proste zapytanie z rozsądnej wielkości tabeli. Zazwyczaj mam wystarczające work_mem, ale w tym przypadku użyłem poleceń

SET work_mem = 64;

ustawić bardzo małe work_memi

SET work_mem = default;

aby ustawić się z work_mempowrotem na tyle, że jest wystarczająco duża dla mojego zapytania.

WYJAŚNIJ I Sprawdź ponownie Stan

Tak, działa tylko z mojej kwerendy EXPLAINjako

EXPLAIN 
SELECT * FROM olap.reading_facts
WHERE meter < 20;

Otrzymałem wyniki zarówno dla niskich, jak i wysokich work_mem:

Niska work_mem

Bitmap Heap Scan on reading_facts  (cost=898.92..85632.60 rows=47804 width=32)
  Recheck Cond: (meter < 20)
  ->  Bitmap Index Scan on idx_meter_reading_facts  (cost=0.00..886.96 rows=47804 width=0)
        Index Cond: (meter < 20)

Wysoki work_mem

Bitmap Heap Scan on reading_facts  (cost=898.92..85632.60 rows=47804 width=32)
  Recheck Cond: (meter < 20)
  ->  Bitmap Index Scan on idx_meter_reading_facts  (cost=0.00..886.96 rows=47804 width=0)
        Index Cond: (meter < 20)

Krótko mówiąc, EXPLAINtylko, zgodnie z oczekiwaniami, plan zapytań wskazuje, że warunek ponownego sprawdzenia jest możliwy, ale nie wiemy, czy zostanie obliczony.

OBJAŚNIJ ANALIZĘ i ponownie sprawdź stan

Po uwzględnieniu ANALYZEw zapytaniu wyniki przekazują nam więcej informacji na temat tego, co musimy wiedzieć.

Niska work_mem

Bitmap Heap Scan on reading_facts  (cost=898.92..85632.60 rows=47804 width=32) (actual time=3.130..13.946 rows=51840 loops=1)
  Recheck Cond: (meter < 20)
  Rows Removed by Index Recheck: 86727
  Heap Blocks: exact=598 lossy=836
  ->  Bitmap Index Scan on idx_meter_reading_facts  (cost=0.00..886.96 rows=47804 width=0) (actual time=3.066..3.066 rows=51840 loops=1)
        Index Cond: (meter < 20)

Wysoki work_mem

Bitmap Heap Scan on reading_facts  (cost=898.92..85632.60 rows=47804 width=32) (actual time=2.647..7.247 rows=51840 loops=1)
  Recheck Cond: (meter < 20)
  Heap Blocks: exact=1434
  ->  Bitmap Index Scan on idx_meter_reading_facts  (cost=0.00..886.96 rows=47804 width=0) (actual time=2.496..2.496 rows=51840 loops=1)
        Index Cond: (meter < 20)

Ponownie, zgodnie z oczekiwaniami, włączenie ANALYZEujawnia nam bardzo ważne informacje. W małym work_memprzypadku widzimy, że wiersze są usuwane przez ponowne sprawdzenie indeksu i że mamy lossybloki sterty.

Wniosek? (lub jego brak)

Niestety wygląda EXPLAINna to, że sam w sobie nie wystarczy wiedzieć, czy ponowne sprawdzenie indeksu będzie faktycznie konieczne, ponieważ niektóre identyfikatory wierszy są odrzucane na rzecz zachowania stron podczas skanowania sterty bitmap.

Używanie EXPLAIN ANALYZEjest odpowiednie do diagnozowania problemów z zapytaniami o średniej długości, ale w przypadku, gdy zapytanie zajmuje bardzo dużo czasu, uruchomienie, EXPLAIN ANALYZEaby przekonać się, że indeks bitmapy przekształca się w stratny z powodu niewystarczającego, work_memjest nadal trudnym ograniczeniem. Chciałbym, aby istniał sposób EXPLAINoszacowania prawdopodobieństwa tego wystąpienia na podstawie statystyk tabeli.

Chris
źródło