Comprensione di "Scansione heap bitmap" e "Scansione indice bitmap"


36

Proverò a spiegare i miei equivoci con il seguente esempio.

Non ho capito i fondamenti di Bitmap Heap Scan Node. Considera la query SELECT customerid, username FROM customers WHERE customerid < 1000 AND username <'user100';il cui piano è questo:

Bitmap Heap Scan on customers  (cost=25.76..61.62 rows=10 width=13) (actual time=0.077..0.077 rows=2 loops=1)
  Recheck Cond: (((username)::text < 'user100'::text) AND (customerid < 1000))
  ->  BitmapAnd  (cost=25.76..25.76 rows=10 width=0) (actual time=0.073..0.073 rows=0 loops=1)
        ->  Bitmap Index Scan on ix_cust_username  (cost=0.00..5.75 rows=200 width=0) (actual time=0.006..0.006 rows=2 loops=1)
              Index Cond: ((username)::text < 'user100'::text)
        ->  Bitmap Index Scan on customers_pkey  (cost=0.00..19.75 rows=1000 width=0) (actual time=0.065..0.065 rows=999 loops=1)
              Index Cond: (customerid < 1000)

La mia comprensione di questo nodo :

Come spiegato qui , la bitmap heap scantabella si blocca in ordine sequenziale, quindi non produce un overhead di accesso casuale alla tabella che accade semplicemente Index Scan.

Dopo che Index Scanè stato fatto, PostgreSQL non sa come recuperare le righe in modo ottimale, per evitare inutili heap blocks reads(o hitsse c'è una cache calda). Quindi per capirlo genera la struttura ( Bitmap Index Scan) chiamata bitmapche nel mio caso viene generata generando due bitmap degli indici ed eseguendo BITWISE AND. Poiché la bitmap è stata generata, ora può leggere la tabella in modo ottimale in un ordine sequenziale, evitando inutili heap I/O-operations.

Questo è il luogo in cui arrivano molte domande.

DOMANDA: Abbiamo solo una bitmap. Come fa PostgreSQL a sapere con una bitmap qualcosa sull'ordine fisico delle righe? O genera la bitmap in modo che qualsiasi elemento di essa possa essere mappato facilmente sul puntatore a una pagina? Se è così, questo spiega tutto, ma è solo una mia ipotesi.

Quindi, possiamo semplicemente dire che bitmap heap scan -> bitmap index scanè come una scansione sequenziale ma solo della parte appropriata della tabella?


Ho scritto una spiegazione di alcuni di questi qui: stackoverflow.com/q/33100637/398670
Craig Ringer,

@CraigRinger Sembra che non abbia spiegato correttamente ciò che non ho capito. Naturalmente, come hai spiegato, abbiamo una bitmap con la quale PostgreSQL legge la tabella in sequenza. Non capisco come possa capire il blocco effettivo designato da una specifica bitmap ad es 001001010101011010101. O in realtà non importa e tutto ciò che dobbiamo sapere è solo che può trovare un blocco dalla sua bitmap in modo abbastanza veloce ...?
Sant'Antario,

Ah, potresti fraintendere che cosa significhi "bitmap" qui. Lasciami seguire in una modifica.
Craig Ringer,

@CraigRinger Forse, ho preso la definizione da .
Sant'Antario,

Risposte:


52

Come fa PostgreSQL a sapere con una bitmap qualcosa sull'ordine fisico delle righe?

La bitmap è un bit per pagina di heap. La scansione dell'indice bitmap imposta i bit in base all'indirizzo della pagina heap a cui punta la voce di indice.

Quindi, quando si esegue la scansione dell'heap di bitmap, esegue solo una scansione della tabella lineare, leggendo la bitmap per vedere se dovrebbe preoccuparsi di una determinata pagina o cercarla.

O genera la bitmap in modo che qualsiasi elemento di essa possa essere mappato facilmente sul puntatore a una pagina?

No, la bitmap corrisponde 1: 1 alle pagine heap.

Ne ho scritto un po 'di più qui .


OK, sembra che potresti fraintendere il significato di "bitmap" in questo contesto.

Non è una stringa un po 'come "101011" creata per ogni pagina heap, per ogni indice letto o altro.

L'intera bitmap è un array a singolo bit , con tanti bit quante sono le pagine heap nella relazione sottoposta a scansione.

Una bitmap viene creata dalla prima scansione dell'indice, iniziando con tutte le voci 0 (false). Ogni volta che viene trovata una voce di indice che corrisponde alla condizione di ricerca, l'indirizzo heap a cui punta quella voce di indice viene cercato come offset nella bitmap e quel bit viene impostato su 1 (vero). Quindi, anziché cercare direttamente la pagina dell'heap, la scansione dell'indice bitmap cerca la posizione bit corrispondente nella bitmap.

La seconda e ulteriore scansione degli indici bitmap fanno la stessa cosa con gli altri indici e le condizioni di ricerca su di essi.

Quindi ogni bitmap viene ANData insieme. La bitmap risultante ha un bit per ogni pagina heap, in cui i bit sono veri solo se erano veri in tutte le singole scansioni dell'indice bitmap, ovvero la condizione di ricerca corrispondente per ogni scansione dell'indice. Queste sono le uniche pagine di heap che dobbiamo preoccuparci di caricare ed esaminare. Poiché ogni pagina dell'heap può contenere più righe, dobbiamo quindi esaminare ciascuna riga per vedere se soddisfa tutte le condizioni - ecco di cosa tratta la parte "ricontrolla cond".

Una cosa cruciale da capire con tutto ciò è che l'indirizzo di tupla in una voce di indice punta alla riga ctid, che è una combinazione del numero di pagina dell'heap e dell'offset all'interno della pagina dell'heap. Una scansione dell'indice bitmap ignora gli offset, poiché controllerà comunque l'intera pagina e imposta il bit se una riga su quella pagina corrisponde alla condizione.


Esempio grafico

Heap, one square = one page:
+---------------------------------------------+
|c____u_____X___u___X_________u___cXcc______u_|
+---------------------------------------------+
Rows marked c match customers pkey condition.
Rows marked u match username condition.
Rows marked X match both conditions.


Bitmap scan from customers_pkey:
+---------------------------------------------+
|100000000001000000010000000000000111100000000| bitmap 1
+---------------------------------------------+
One bit per heap page, in the same order as the heap
Bits 1 when condition matches, 0 if not

Bitmap scan from ix_cust_username:
+---------------------------------------------+
|000001000001000100010000000001000010000000010| bitmap 2
+---------------------------------------------+

Una volta create le bitmap, viene eseguito un AND bit a bit su di esse:

+---------------------------------------------+
|100000000001000000010000000000000111100000000| bitmap 1
|000001000001000100010000000001000010000000010| bitmap 2
 &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|000000000001000000010000000000000010000000000| Combined bitmap
+-----------+-------+--------------+----------+
            |       |              |
            v       v              v
Used to scan the heap only for matching pages:
+---------------------------------------------+
|___________X_______X______________X__________|
+---------------------------------------------+

La scansione dell'heap bitmap cerca quindi l'inizio di ogni pagina e legge la pagina:

+---------------------------------------------+
|___________X_______X______________X__________|
+---------------------------------------------+
seek------->^seek-->^seek--------->^
            |       |              |
            ------------------------
            only these pages read

e ogni pagina letta viene quindi ricontrollata rispetto alla condizione poiché può esserci> 1 riga per pagina e non tutte necessariamente corrispondono alla condizione.


Ah, ecco cosa intendevano popolando la bitmap.
Sant'Antario,

@Antario Ho aggiunto elementi grafici per spiegare
Craig Ringer,

Consentitemi di chiarire un'altra cosa sulla scansione bitmap. Hai detto che abbiamo una bitmap 1: 1 per heap delle pagine e possiamo determinare una pagina heap da un indice bit nella bitmap. Poiché la relazione può contenere pagine su un disco in un ordine non sequenziale (non raggruppato), non è del tutto chiaro come possiamo determinare l'indirizzo di una pagina semplicemente sfalsando in una bitmap. Presumo che il pianificatore sappia come calcolare un indirizzo di pagina in offset per una data relazione . È vero?
Sant'Antario,

1
Quindi dobbiamo mettere tutte le pagine che sono su un disco. Inoltre, i dati della relazione potrebbero essere diffusi su due o più unità (quindi è difficile immaginare un ordine lineare delle pagine della relazione ), quindi è difficile determinare l'offset effettivo della pagina successiva. Perché credo che per "offset" intendevi l'offset fisico effettivo corrispondente a una posizione fisica su un'unità.
Sant'Antario,

2
PostgreSQL non si preoccupa minimamente delle unità. Si preoccupa solo dei file nel file system . Il file logico per la relazione è lineare e contiguo, ed è quello che è finita la bitmap. (Potrebbero esserci più estensioni al file, ma vengono trattate come se fossero aggiunte in continuazione e la bitmap è su tutte). Stai guardando il livello di astrazione sbagliato. (In una nota a margine, la bitmap in una scansione dell'indice bitmap non viene nemmeno calcolata dal planner, fa parte del metodo di accesso all'indice btree e si riferisce più all'esecutore che al planner).
Craig Ringer,

3

Si prega di fare riferimento al mio post sul blog https://rajeevrastogi.blogspot.in/2018/02/bitmap-scan-in-postgresql.html?showComment=1518410565792#c4647352762092142586 per la descrizione dettagliata della scansione bitmap in PostgreSQL.

Panoramica generale delle funzionalità rapide della scansione bitmap:

  1. Scansione Bitmap Heap richiede una tupla da Scansione indice bitmap.

  2. Scansione indice bitmap esegue la scansione dell'indice secondo la condizione quasi nello stesso modo della normale scansione indice. Invece di restituire TID (costituito da n. Di pagina e offset all'interno di quello) corrispondente ai dati di heap, aggiunge tali TID in una bitmap. Per una semplice comprensione, puoi considerare che questa bitmap contiene hash di tutte le pagine (hash basato sul numero di pagina) e ogni voce di pagina contiene un array di tutti gli offset all'interno di quella pagina.

  3. Quindi Bitmap Heap Scan legge la bitmap per ottenere i dati dell'heap corrispondenti al numero di pagina memorizzato e all'offset. Quindi controlla la visibilità, la qualificazione ecc. E restituisce la tupla in base all'esito di tutti questi controlli.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.