Bir sorguyu `NEREDE alanı NULL`dir?


14

Ben alanlardan birini ( uploaded_at) ayarını ekler bir sürü ile bir tablo var NULL. Daha sonra periyodik bir görev tüm tuples'ları seçer WHERE uploaded_at IS NULL, bunları işler ve günceller, uploaded_atgüncel tarihe ayarlar .

Tabloyu nasıl indekslemeliyim?

Anlamak gibi kısmi bir dizin kullanmanız gerektiğini anlıyorum:

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

Ya da böyle bir şey. Her zaman olan bir alan üzerinde dizin doğru ise biraz kafam karıştı NULL. Veya bir b-ağacı dizini kullanmak doğruysa. Hash daha iyi bir fikir gibi görünüyor, ancak eski ve sıcak bekleme çoğaltması akışı ile çoğaltılmıyor. Herhangi bir tavsiye büyük mutluluk duyacağız.

Aşağıdaki endekslerle biraz deneme yaptım:

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

ve sorgu planlayıcısı her zaman foo_partdizini seçiyor gibi görünüyor . explain analyseayrıca foo_partendeks için biraz daha iyi sonuç verir :

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

Yanıtlar:


10

Bu özel durumda, aslında endekslenen sütun eldeki sorgu için önemsizdir. İstediğiniz sütunu seçebilirsiniz. Başka bir şey seçerdim uploaded_at, ki bu işe yaramaz. Diğer sorgular için yararlı olabilecek ve ideal olarak 8 bayttan büyük olmayan bazı sütunlar.

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

Başka bir sütun için kullanım durumunuz yoksa, işe yaramazsa sadık kalmak en iyisidir uploaded_at, bu nedenle dizin için ek bakım maliyeti ve SICAK güncellemeler için kısıtlamalar getirmemek. Daha:

Veya başka bir dizin sütunu kullanmıyorsanız sabit ifadesini dizin ifadesi olarak kullanın. Sevmek:

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

Parantez gereklidir. Bu da indeksi minimum boyutta tutar. Ancak dizin sütunu hiçbir zaman 8 bayttan (bu durumda timestamp) daha büyük olmasa da yine de minimum boyuttadır. İlişkili:


idÖrneğin bir seri alan olabilir mi?
Kirill Zaitsev

1
@teferi: a serialherhangi biri kadar iyidir. Mesele, bundan faydalanmak için gerçekten sorgular olup olmadığıdır.
Erwin Brandstetter
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.