lesson ── postgres-labs ── ~24 мин ── 4 шагов
Возьмём запрос с ::date-кастом, который убивает индекс, прочитаем
EXPLAIN ANALYZE и починим переписыванием на диапазон. Перед фиксом
предскажи, сменится ли Seq Scan на индексный доступ. Запусти psql
во вкладке client.
интерактивный sandbox
Поднимется контейнер postgreslab/postgres-base с PostgreSQL 17 и psql. В браузере откроется терминал, база lab уже настроена. Каждый шаг проверяется автоматически. Сеть air-gapped, наружу контейнер не ходит.
stack ── PostgreSQL 17 · psql · 1 GB RAM · air-gapped · самоуничтожается через 45 мин простоя
CREATE TABLE ev AS
SELECT g AS id, now() - (g || ' minutes')::interval AS at
FROM generate_series(1, 200000) g;
CREATE INDEX ON ev(at);
ANALYZE ev;
Индекс по at - то, что каст потом сделает бесполезным.
✓ Таблица и индекс по at готовы.
EXPLAIN ANALYZE SELECT * FROM ev WHERE at::date = current_date;
Заметь Seq Scan: at::date оборачивает колонку в функцию, и индекс
по at не подходит. Посмотри расхождение estimated/actual rows.
Функция или каст над индексированной колонкой делает условие не-sargable.
✓ Seq Scan - каст обернул колонку, индекс не использован.
Не трогай колонку, сравнивай её саму:
EXPLAIN ANALYZE SELECT * FROM ev
WHERE at >= current_date AND at < current_date + 1;
Условие стало sargable - планировщик берёт индекс (Index или Bitmap Scan). Предскажи тип узла перед проверкой.
Диапазон по самой колонке at позволяет использовать индекс.
✓ Индексный доступ вернулся - условие стало sargable.
EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM ev
WHERE at >= current_date AND at < current_date + 1;
В строке Buffers видно shared hit/read. Sargable-вариант
трогает куда меньше страниц, чем Seq Scan по всей таблице.
shared read - чтения с диска, shared hit - попадания в кеш.
✓ Видно BUFFERS - sargable-запрос читает меньше страниц.
EXPLAIN ANALYZE кладёт факт рядом с оценкой; расследование - поиск узла с наибольшим расхождением rows. Типовой виновник - каст или функция над индексированной колонкой: условие становится не-sargable и уходит в Seq Scan. Лечение - переписать на диапазон по самой колонке. BUFFERS показывает, упор в диск или в вычисления.
команды
EXPLAIN (ANALYZE, BUFFERS) SELECT ...;факт, оценка и страницы рядомWHERE at >= d AND at < d + 1sargable-диапазон вместо at::date = dконцепции