Postgresql
如何使用“WHERE field IS NULL”索引查詢?
我有一個包含很多插入的表,將其中一個欄位 (
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
),但它仍然是最小大小。有關的: