Come indicizzare una query con `WHERE field IS NULL`?


14

Ho una tabella con molti inserti, impostando uno dei campi ( uploaded_at) su NULL. Quindi un'attività periodica seleziona tutte le tuple WHERE uploaded_at IS NULL, le elabora e aggiorna, impostando la uploaded_atdata corrente.

Come devo indicizzare la tabella?

Capisco che dovrei usare un indice parziale come:

CREATE INDEX foo ON table (uploaded_at) WHERE uploaded_at IS NULL

O smth così. Sono un po 'confuso, però, se è corretto indicizzare su un campo che è sempre NULL. O se è corretto usare un indice b-tree. L'hash sembra un'idea migliore, ma è obsoleta e non viene replicata tramite la replica in streaming hot-standby. Qualsiasi consiglio sarebbe molto apprezzato.

Ho sperimentato un po 'con i seguenti indici:

"foo_part" btree (uploaded_at) WHERE uploaded_at IS NULL
"foo_part_id" btree (id) WHERE uploaded_at IS NULL

e la query planer sembra scegliere sempre l' foo_partindice. explain analyseproduce anche risultati leggermente migliori per l' foo_partindice:

Index Scan using foo_part on t1  (cost=0.28..297.25 rows=4433 width=16) (actual time=0.025..3.649 rows=4351 loops=1)
   Index Cond: (uploaded_at IS NULL)
 Total runtime: 4.060 ms

vs

Bitmap Heap Scan on t1  (cost=79.15..6722.83 rows=4433 width=16) (actual time=1.032..4.717 rows=4351 loops=1)
   Recheck Cond: (uploaded_at IS NULL)
   ->  Bitmap Index Scan on foo_part_id  (cost=0.00..78.04 rows=4433 width=0) (actual time=0.649..0.649 rows=4351 loops=1)
 Total runtime: 5.131 ms

Risposte:


10

In questo caso speciale la colonna effettivamente indicizzata è irrilevante per la query a portata di mano. Puoi scegliere qualsiasi colonna. Sceglierei qualcos'altro uploaded_at, che è inutile. Alcune colonne che possono essere utili per altre query e non sono più grandi di 8 byte, idealmente.

CREATE INDEX foo ON table bar (some_col) WHERE uploaded_at IS NULL;

Se non hai alcun caso d'uso per altre colonne, è comunque meglio attenersi agli inutili uploaded_at, quindi non introdurre costi di manutenzione aggiuntivi per l'indice e restrizioni per gli aggiornamenti HOT. Di Più:

Oppure utilizza una costante come espressione di indice se non hai alcuna utilità per qualsiasi altra colonna di indice. Piace:

CREATE INDEX baz ON table bar ((TRUE)) WHERE uploaded_at IS NULL;

Sono necessarie le parentesi. Ciò mantiene anche l'indice alla dimensione minima. Ma mentre la colonna dell'indice non è mai più grande di 8 byte (che è il caso timestamp) è comunque comunque alla dimensione minima. Relazionato:


Potrebbe essere forse un idcampo seriale per esempio?
Kirill Zaitsev,

1
@teferi: a serialè buono come un altro. Il punto è se ci sono effettivamente query per farne uso.
Erwin Brandstetter,
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.