План показывает полный просмотр: одна строка подошла, почти 100 миллионов отброшены фильтром, выполнение заняло около 10,35 секунды. Для селективного равенства нужен индекс по title.
Есть таблица, в ней 100_000_000 записей
План показывает полный просмотр: одна строка подошла, почти 100 миллионов отброшены фильтром, выполнение заняло около 10,35 секунды. Для селективного равенства нужен индекс по title.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Есть таблица, в ней 100_000_000 записей
CREATE TABLE posts ( id BIGSERIAL PRIMARY KEY, title VARCHAR(255) NOT NULL, text TEXT NOT NULL ); #######################################
Запрос: SELECT * FROM posts WHERE title = 'Python tutorial';
План выполнения:
Seq Scan on posts (cost=0.00..20834.00 rows=1 width=64) (actual time=0.025..10350.421 rows=1)
Filter: (title = 'Python tutorial') Rows Removed by Filter: 99999999
Planning Time: 0.120 ms Execution Time: 10350.500 ms
Что видно из этого плана? Как можно оптимизировать?
Ответ
План показывает полный просмотр: одна строка подошла, почти 100 миллионов отброшены фильтром, выполнение заняло около 10,35 секунды. Для селективного равенства нужен индекс по title.
Первичный ключ id не помогает условию по title. Возможный индекс:
CREATE INDEX CONCURRENTLY posts_title_idx ON posts (title);
На большой рабочей таблице такую операцию планируют с учётом нагрузки, места и ограничений concurrent-создания; это не команда для бесконтрольного запуска. Затем обновляют статистику при необходимости и сравнивают план. SELECT * требует получить text из таблицы, но при одной найденной записи это обычно несравнимо дешевле полного просмотра. Значения cost — оценки в условных единицах, не миллисекунды.