Как количество записей влияет на производительность базы данных
Что проверяют
Понимаете ли вы, что рост таблицы бьёт по запросам неодинаково: поиск по индексу почти не замечает лишний миллион строк, а полное сканирование и OFFSET деградируют линейно. Следом просят рассказать, как вы находили медленный запрос и что с ним сделали.
Как отвечать
Разложите ответ по механизмам:
- индекс против сканирования: поиск по B-tree стоит O(log n), у дерева на десятки миллионов строк три или четыре уровня. Без подходящего индекса база читает всю таблицу, и время растёт линейно;
- память: пока горячие данные и индексы помещаются в кэш (
shared_buffersв PostgreSQL плюс кэш ОС), запросы быстрые. Когда рабочий набор перерастает память, начинается чтение с диска, и деградация наступает резко, а не плавно; - пагинация:
OFFSET 100000заставляет базу прочитать и выбросить сто тысяч строк. Для глубоких страниц нужна keyset-пагинация:WHERE id > :last_id ORDER BY id LIMIT 50; - *`COUNT()`**: в PostgreSQL из-за MVCC точный подсчёт требует обхода таблицы или индекса. На больших объёмах счётчик хранят отдельно или берут оценку из статистики;
- запись и обслуживание: каждый индекс замедляет
INSERTиUPDATE, растёт bloat, autovacuum не успевает, статистика устаревает, и планировщик выбирает плохой план. Для очень больших таблиц помогает партиционирование по дате.
Со стороны Python добавьте то, что зависит от ORM. list(queryset) в Django тянет всю выборку в память, для больших объёмов есть .iterator(), а в SQLAlchemy yield_per(). Массовую вставку делают через bulk_create или COPY, а не циклом по одной строке. Диагностика начинается с EXPLAIN (ANALYZE, BUFFERS).
Где спотыкаются
Говорят «больше записей, значит всё медленнее» без оговорок. Интервьюер ждёт разделения: точечные запросы по индексу почти не меняются, страдают сканирования, сортировки и агрегаты.
Проверяют запросы на локальной базе в тысячу строк. Там планировщик честно выбирает последовательное сканирование, и проблема всплывает только на проде.
Лечат всё индексами. Лишний индекс на таблице с интенсивной записью замедляет вставку, а запрос с функцией над колонкой или LIKE '%...%' обычный индекс всё равно не использует.