Как индексировать запрос с помощью поля `WHERE IS is 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
Кирилл Зайцев
источник

Ответы:

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поле, например?
Кирилл Зайцев
1
@teferi: а serialтак же хорош, как и любой. Дело в том, есть ли на самом деле запросы, чтобы использовать его.
Эрвин Брандштеттер