Postgresql

如何使用“WHERE field IS NULL”索引查詢?

  • May 18, 2018

我有一個包含很多插入的表,將其中一個欄位 ( uploaded_at) 設置為NULL. 然後周期性任務選擇所有元組WHERE uploaded_at IS NULL,處理它們並更新,設置uploaded_at為目前日期。

我應該如何索引表?

我知道我應該使用部分索引,例如:

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

或者那樣的。我有點困惑,但如果在始終為NULL. 或者如果使用 b-tree 索引是正確的。散列看起來是一個更好的主意,但它已經過時並且不能通過流式熱備複製進行複制。任何建議將不勝感激。

我對以下指標進行了一些實驗:

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

並且查詢計劃似乎總是選擇foo_part索引。也為指數explain analyse產生了稍微好一點的結果:foo_part

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

對比

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

在這種特殊情況下,實際索引的列與手頭的查詢無關。您可以選擇任何列。我會選擇除 之外的其他東西uploaded_at,這是沒用的。一些可能對其他查詢有用的列,理想情況下不大於 8 個字節。

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

如果你沒有任何其他列的案例,最好還是堅持 useless uploaded_at,這樣就不會引入額外的索引維護成本和 HOT 更新的限制。更多的:

或者,如果您對任何其他索引列沒有用處,則使用***常量作為索引表達式。***喜歡:

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

需要括號。這也使索引保持在最小大小。但是,雖然索引列永遠不會大於 8 個字節(這是 的情況timestamp),但它仍然是最小大小。有關的:

引用自:https://dba.stackexchange.com/questions/81620