Маленькая техническая заметка про SQL. Такая: если в таблице есть поле created_at, по нему должен быть btree-индекс. Если поля нет, его нужно добавить вместе с индексом.

Объяснение следующее. Срез по времени – это самая частая задача в работе с данными. Если не фиксировать время события, это обернется бедой.

Эти два дня я отлаживал серьезный баг, о котором напишу отдельно. Но попутно выяснилось следующее. В базе данных есть таблица, которая фиксирует изменения сущностей. В ней один индекс – айди сущности. Это хорошо, если требуется расследовать конкретную сущность. Но оказалось, пострадало их много за определенный период, так что этот индекс бесполезен.

Я хотел выбрать события по времени, благо интервал небольшой, всего неделя. Но оказалось, что у поля created_at нет индекса. В таблице 400 миллионов записей, и отбор по нему работает страшно медленно: limit 10 занимает 8 минут.

Добавить индекс в такую таблицу – страшно дорого. Это нужно делать ночью на выходных, кто на это пойдет?

Скажете: используй create index CONCURRENTLY. А я скажу, что конкурентный индекс не работает для партицированных таблиц, а наша именно такая. Нужно делать либо обычный индекс в лоб, либо создавать конкурентный индекс для каждой партиции. Все сложно.

По факту таблица превратилась в черную дыру: в нее все входит, но ничего не выходит. Она беспомощна из-за своей массы. Разве что можно найти данные по конкретной сущности, но этого часто недостаточно.

Время – ключевой фактор при расследовании инцидентов. Даже если в таблице миллиард записей, границы времени известны хотя бы примерно. Можно выбрать срез и дальше обработать его вручную. А если индекса нет, мы лишили себя такой возможности. Сами себе Буратины.

Поэтому – индекс по времени должен быть всегда и обязательно.