Какие типы сканирования таблиц существуют
Что проверяют
Умеете ли вы понять, почему запрос из вашего сервиса тормозит, и дойти от ORM до плана выполнения. Обычно следом дают запрос на Django или SQLAlchemy и спрашивают, какой тип сканирования будет и как это проверить.
Как отвечать
Типы сканирования называйте на примере PostgreSQL, с которым чаще всего работают Python-сервисы:
- Seq Scan: чтение всей таблицы. Нормален для маленьких таблиц и выборок большой доли строк;
- Index Scan: поиск по индексу и дочитывание строк из таблицы. Выгоден при высокой селективности, например при поиске по первичному ключу;
- Index Only Scan: все нужные колонки уже в индексе, таблица почти не читается. Зависит от карты видимости, которую обновляет
VACUUM; - Bitmap Heap Scan: сначала по индексу собирается карта подходящих страниц, потом они читаются по порядку. Средняя селективность, комбинации условий через
OR; - Parallel Seq Scan: полное чтение несколькими процессами на больших таблицах.
В MySQL то же видно в колонке type у EXPLAIN: ALL означает полное сканирование, а range, ref, eq_ref, const это разные варианты работы через индекс.
Из Python план получают так: в Django QuerySet.explain(analyze=True), в SQLAlchemy выполняют EXPLAIN ANALYZE над скомпилированным запросом. Сами запросы видно в django-debug-toolbar или в логе движка с echo=True. Смотреть надо на тип узла, оценку строк против фактической и время.
Выбор делает планировщик по статистике, собранной ANALYZE. Если оценка сильно расходится с фактом, начинайте со статистики, а не с новых индексов.
Где спотыкаются
Не замечают, что ORM сгенерировала неиндексируемое условие. filter(name__icontains="ann") в Django на PostgreSQL превращается в UPPER(...) LIKE UPPER('%ann%'), и обычный B-tree тут бесполезен. Нужен триграммный GIN-индекс (pg_trgm) по тому же выражению или полнотекстовый поиск.
Считают Seq Scan ошибкой всегда. На выборке трети таблицы он дешевле тысяч случайных чтений по индексу.
Выдумывают отдельный «скан по первичному ключу». Это обычный Index Scan по уникальному индексу, а медленным сервис чаще делает не он, а N+1 запросов, которые лечатся select_related и prefetch_related.