如何使用“ WHERE字段为NULL”索引查询?


14

我的桌子上有很多插入物,将(uploaded_at)字段之一设置为NULL。然后,定期任务选择所有元组WHERE uploaded_at IS NULL,对其进行处理并更新,将其设置uploaded_at为当前日期。

我应该如何索引表?

我了解我应该使用部分索引,例如:

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

或类似的东西。我有点困惑,但是如果对一个始终为的字段进行索引是正确的话NULL。或者使用b树索引是否正确。哈希看起来是个更好的主意,但是它已经过时了,不能通过流热备份复制来复制。任何建议将不胜感激。

我已经尝试了以下索引:

"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

Answers:


10

在这种特殊情况下,实际索引的列与手头查询无关。您可以选择任何列。我会选择以外的其他东西uploaded_at,这是没有用的。理想情况下,某些列可能对其他查询有用,并且不大于8个字节。

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

如果您没有其他任何用例的用例,那么仍然最好坚持使用无用的列uploaded_at,以免引入额外的索引维护成本和HOT更新限制。更多:

或者,如果不使用任何其他索引列,则使用常量作为索引表达式。喜欢:

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

需要括号。这也使索引保持最小大小。但是,尽管索引列从不大于8个字节(对于这种情况timestamp),但无论如何它仍处于最小大小。有关:


id例如,可能是串行字段吗?
Kirill Zaitsev 2014年

1
@teferi:一个serial和其他的一样好。关键是实际上是否存在查询要使用它。
Erwin Brandstetter,2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.