Комментарии 9
При разработке БД хорошо помнить правило — все, что делается часто и над большим количеством строк, должно делаться за логарифмическое время. Если вы можете обмануть природу за счёт частного случая (например, высокого отношения r/w, что позволяет хранить/индексировать корни тредов, как в посте, и/или использовать индексы) — вам повезло
Интересно, кто-то проводил сравнения планов запросов и размеров таблиц, при количестве строк порядка 1000.
seq_page_cost/cpu_tuple_cost
весьма велики шансы просто получать почти всегда Seq Scan
.Я наивно полагаю, что при тысяче записей нет причин заморачиваться с эффективностью запроса, вся таблица может уместиться в несколько 4-кБ секторов диска, да и мне кажется, что будут другие таблицы, которые будут оказывать на порядок большее влияние, чем эта.
Впрочем, если этот запрос многократно проходится по всем элементам таблицы, работает за экспоненциальное время, или таблица широкая, или содержит блобы, то да, надо что-то менять: или запрос, или таблицу. Или всё вынести в память, или громоздкие вычисления проводить предварительно.
Будет ли запрос эффективнее рекурсивного?
WITH RECURSIVE T AS (
SELECT 1 i
UNION ALL
SELECT i + 1 FROM T WHERE i < 100
)
TABLE T;
SELECT generate_series(1, 100) i;
Результат одинаковый, а разница по времени в конкретном вырожденном случае до 10-15 раз.
Кроме того, table scan — очень опасная операция в плане блокировок — так как будет либо залочена вся таблица, либо сразу большой диапазон. Другие треды будут в лучшем случае ждать, а в худшем — придет дедушка лок. Индексные же операции чаще всего требуют точечных локов только нужных строк, и вероятность пересечься с другим тредом на нем же существенно меньше.
В общем, даже 100 строк (особенно, если r/(r+w) достаточно высокое) и выборки частые, выиграют от использования индекса
PostgreSQL Antipatterns: «Бесконечность — не предел!», или Немного о рекурсии