Bagaimana cara mengindeks kueri dengan `WHERE is IS NULL`?


14

Saya punya tabel dengan banyak sisipan, mengatur salah satu bidang ( uploaded_at) ke NULL. Kemudian tugas berkala memilih semua tupel WHERE uploaded_at IS NULL, memprosesnya dan memperbarui, mengatur uploaded_atke tanggal saat ini.

Bagaimana saya harus mengindeks tabel?

Saya mengerti bahwa saya harus menggunakan indeks parsial seperti:

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

Atau pertanda seperti itu. Saya agak bingung meskipun apakah itu benar untuk mengindeks pada bidang yang selalu NULL. Atau jika benar menggunakan indeks b-tree. Hash terlihat seperti ide yang lebih baik, tetapi sudah usang dan tidak direplikasi melalui streaming replikasi hot-standby. Saran apa pun akan sangat dihargai.

Saya telah bereksperimen sedikit dengan indeks berikut:

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

dan perencana kueri tampaknya selalu memilih foo_partindeks. explain analysejuga menghasilkan hasil yang sedikit lebih baik untuk foo_partindeks:

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

Jawaban:


10

Dalam kasus khusus ini, kolom yang diindeks sebenarnya tidak relevan untuk kueri. Anda dapat memilih kolom mana saja. Saya akan memilih sesuatu yang lain daripada uploaded_at, yang tidak berguna. Beberapa kolom yang mungkin berguna untuk permintaan lain dan tidak lebih besar dari 8 byte, idealnya.

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

Jika Anda tidak menggunakan kasing untuk kolom lainnya, tetap yang terbaik adalah tetap menggunakan yang tidak berguna uploaded_at, jadi jangan masukkan biaya pemeliharaan tambahan untuk indeks dan pembatasan untuk pembaruan HOT. Lebih:

Atau gunakan konstanta sebagai ekspresi indeks jika Anda tidak menggunakan kolom indeks lainnya. Suka:

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

Diperlukan tanda kurung. Ini juga menjaga indeks pada ukuran minimum. Tetapi sementara kolom indeks tidak pernah lebih besar dari 8 byte (yang merupakan kasus untuk timestamp) itu masih pada ukuran minimum. Terkait:


Mungkinkah itu menjadi idbidang serial misalnya?
Kirill Zaitsev

1
@teferi: a serialsebagus apapun. Intinya adalah apakah sebenarnya ada pertanyaan untuk memanfaatkannya.
Erwin Brandstetter
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.