linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
Intro
Lessons
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Главы
  • How it worksскоро
  • Уроки
  • База знаний
  • Собеседование
home/postgres/lessons/pg-lab-37-1-index-design

lesson ── postgres-labs ── ~24 мин ── 5 шагов

Составной индекс против Seq Scan плюс Sort

Соберём частый паттерн «последние записи в ветке» и уберём дорогую сортировку правильным составным индексом, заодно проверим правило префикса и найдём неиспользуемые индексы. Запусти psql во вкладке client.

▶ интерактивный sandbox

Поднимется контейнер postgreslab/postgres-base с PostgreSQL 17 и psql. В браузере откроется терминал, база lab уже настроена. Каждый шаг проверяется автоматически. Сеть air-gapped, наружу контейнер не ходит.

запустить sandbox →

stack ── PostgreSQL 17 · psql · 1 GB RAM · air-gapped · самоуничтожается через 45 мин простоя

Шаги

  1. 01

    Создай таблицу репозиториев

    sql
    CREATE TABLE repos AS
    SELECT g id, (g % 5000) AS forked_from_id,
           '2026-01-01'::timestamptz + (g || ' min')::interval AS updated_at,
           'repo' || g AS name
    FROM generate_series(1, 500000) g;
    ANALYZE repos;
    подсказка

    Паттерн: много форков от одного репозитория, нужны последние по времени.

    ✓ Таблица repos готова.

  2. 02

    Без индекса: Seq Scan плюс Sort

    sql
    EXPLAIN SELECT * FROM repos
    WHERE forked_from_id = 42 ORDER BY updated_at DESC LIMIT 10;

    Предскажи: какой метод доступа и есть ли узел Sort? (Ожидается Seq Scan и Sort - большой cost.)

    подсказка

    Без индекса надо прочитать все строки ветки и отсортировать.

    ✓ Seq Scan + Sort - дорого. Сейчас починим.

  3. 03

    Составной индекс убирает сортировку

    sql
    CREATE INDEX repos_fork_upd ON repos (forked_from_id, updated_at DESC);
    ANALYZE repos;
    EXPLAIN SELECT * FROM repos
    WHERE forked_from_id = 42 ORDER BY updated_at DESC LIMIT 10;

    Индекс находит участок forked_from_id = 42, где строки уже отсортированы по updated_at DESC - бери первые 10. Sort исчез.

    подсказка

    Равенство раньше, сортировка в конце ключа - тогда ORDER BY бесплатен.

    ✓ Index Scan, сортировка ушла - cost упал на порядки.

  4. 04

    Правило префикса: средняя колонка не помогает

    sql
    EXPLAIN SELECT * FROM repos WHERE updated_at > '2026-06-01';

    Индекс (forked_from_id, updated_at) отсортирован сначала по forked_from_id. Условие только по updated_at не фиксирует префикс - записи разбросаны, индекс не подходит. Предскажи: Seq Scan.

    подсказка

    Индекс (a,b) помогает по a и (a,b), но не по одному b.

    ✓ Seq Scan - по средней колонке составной индекс не работает.

  5. 05

    Найди неиспользуемый индекс

    Заведём индекс и ни разу им не воспользуемся:

    sql
    CREATE INDEX repos_name_unused ON repos (name);
    SELECT indexrelname, idx_scan FROM pg_stat_user_indexes WHERE relname = 'repos';

    У repos_name_unused idx_scan = 0 - им никто не пользуется, это кандидат на удаление (налог на запись без пользы).

    подсказка

    idx_scan = 0 значит, что индексом ни разу не воспользовались.

    ✓ idx_scan = 0 - неиспользуемый индекс найден.

Что ты узнал

Составной индекс (forked_from_id, updated_at DESC) убирает Sort в запросе ORDER BY ... LIMIT: строки уже отсортированы внутри участка. Правило префикса: индекс (a,b) помогает по a и (a,b), но не по одному b. Каждый индекс - налог на запись; неиспользуемые (idx_scan=0) удаляют.

команды

  • CREATE INDEX ON t (a, b DESC);составной индекс под WHERE a ORDER BY b
  • SELECT indexrelname, idx_scan FROM pg_stat_user_indexes;найти неиспользуемые индексы

концепции

  • · порядок колонок: равенство раньше, сортировка/диапазон в конце
  • · составной индекс убирает Sort для ORDER BY + LIMIT
  • · правило префикса: по средней колонке индекс не работает
  • · неиспользуемый индекс (idx_scan=0) - налог на запись без пользы

← предыдущая

BRIN на временно́м ряде против B-tree

следующая →

Запусти физический standby и измерь, как он догоняет primary

Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки