Як проіндексувати запит за допомогою "WHERE field 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: a так serialсамо добре, як і будь-який. Справа в тому, чи є насправді запити для їх використання.
Erwin Brandstetter
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.