Размер SQL индекса: формула и онлайн-калькулятор

💻 IT и кодОбновлено: 13 июля 2026 г.5 мин чтения
Неправильная оценка размера индекса — частая причина замедления запросов и неожиданного переполнения диска. В этой статье — точная формула, пошаговый расчёт на реальных данных и онлайн-калькулятор, чтобы вы могли прикинуть размер до создания индекса.
⚡ Коротко: главное
  • Размер B-дерева индекса ≈ (количество страниц) × (размер страницы), где число страниц = ceil(записей / (размер страницы / (размер ключа + указатель))).
  • Для INT-ключа (4 байта) и указателя (6 байт) на странице 8 КБ помещается ~819 записей. Индекс на 1 млн строк займёт ~9,8 МБ (только листья).
  • Композитный индекс из двух INT занимает 8 байт ключа + 6 байт указателя, на страницу влезает ~585 записей — на 40% больше страниц, чем для одного INT.
  • Инструмент «Калькулятор размера SQL индекса» автоматически применяет формулу и учитывает фрагментацию.
  • Реальный размер индекса в PostgreSQL можно проверить через pg_relation_size, а в MySQL — через information_schema.STATISTICS.

Зачем знать размер индекса до его создания

Большой индекс не ускоряет запросы, а замедляет вставку и потребляет память в Buffer Pool. Зная размер заранее, вы можете:

  • Оценить, войдёт ли индекс целиком в innodb_buffer_pool_size (MySQL) или shared_buffers (Pg).
  • Спланировать место на диске (особенно при создании индекса CONCURRENTLY — нужна временная копия).
  • Выбрать состав индекса (покрывающий или нет) и порядок колонок.

С помощью Калькулятора размера SQL индекса можно не вспоминать формулы, а сразу получить оценку.

Формула размера B-дерева индекса (на примере InnoDB и PostgreSQL)

Большинство СУБД (MySQL InnoDB, PostgreSQL, Oracle) используют B-деревья. Размер индекса складывается из:

Общий размер (байт) = Количество страниц × Размер страницы

Где количество страниц зависит от числа строк и заполненности (fill factor):

Строк на странице = floor(Размер страницы / (Размер ключа + Размер указателя))
Количество страниц = ceil(Число строк / Строк на странице) × (1 + Коэффициент ветвления / ...)

Для InnoDB размер страницы по умолчанию — 16 384 байта (16 КБ). Размер ключа — сумма байт всех колонок индекса + служебные поля (1-2 байта на колонку для NULL). Размер указателя на строку (или страницу) — 6 байт.

Для PostgreSQL размер страницы — 8 192 байта (8 КБ), размер указателя — тоже 6 байт. Fill factor по умолчанию 90% (заполняется 90% страницы, чтобы оставить место для вставок).

Пошаговый пример: считаем размер индекса на 1 млн записей

Предположим, таблица users с 1 000 000 строк. Cоздаём индекс по полю email — VARCHAR(255) в UTF-8. Реальный размер ключа зависит от данных; примем среднюю длину 20 байт + 2 байта длины (varchar). Итого ключ = 22 байта.

  1. Вычисляем строк на страницу (InnoDB): floor(16384 / (22 + 6)) = floor(16384 / 28) = 585.
  2. Количество листовых страниц: ceil(1 000 000 / 585) = 1710.
  3. Высота дерева: каждая внутренняя страница хранит до floor(16384 / (22+6)) = 585 указателей. Для 1710 листьев нужно ceil(1710 / 585) = 3 страницы второго уровня, итого 1 корень. Всего страниц: 1710 + 3 + 1 = 1714.
  4. Общий размер: 1714 × 16384 = 28 114 176 байт ≈ 26,8 МБ (без учёта фрагментации).
Реальный размер может быть на 10-20% больше из-за внутренней фрагментации и служебных данных страниц (page header ~100 байт на страницу). Для точной оценки используйте Калькулятор размера SQL индекса.

Композитные индексы: как растёт размер

Добавление колонок увеличивает ключ, что уменьшает количество строк на страницу. Пример: индекс на (city, status) — city VARCHAR(50) средняя 10 байт + 2 байта длины, status INT (4 байта). Ключ = 10+2+4 = 16 байт + 1 байт nullable = 17 байт. Строк на страницу: floor(16384 / (17+6)) = 712. Для 1 млн строк: ceil(1 000 000 / 712) = 1405 страниц. Размер = 1405 × 16384 ≈ 21,9 МБ.

Количество колонок напрямую влияет на размер. Практические рекомендации:

  • Индекс только на INT (4 байта) — строк на страницу ~1638, на 1 млн — ~584 страницы, ~9,1 МБ.
  • Индекс на VARCHAR(255) с полной длиной (в UTF-8 3 байта на символ = 765 байт) — строк на страницу ~19, на 1 млн — ~52632 страниц, ~822 МБ.

Вывод: не включайте в индекс длинные текстовые поля без крайней необходимости. Для покрытия запроса лучше использовать покрывающий индекс (include columns) в PostgreSQL или secondary index с INCLUDE в MySQL (с 8.0).

Этапы расчёта размера индекса
  1. 1
    1. Определите СУБД и размер страницы

    MySQL InnoDB: 16 384 байта, PostgreSQL: 8192 байта.

  2. 2
    2. Рассчитайте размер ключа

    Суммируйте размеры всех колонок: INT=4, VARCHAR(N)=средняя длина в байтах + 2, DATETIME=5.

  3. 3
    3. Вычислите строк на страницу

    floor(размер_страницы / (размер_ключа + 6)).

  4. 4
    4. Оцените количество страниц

    ceil(количество_строк / строк_на_страницу) с учётом fill factor.

  5. 5
    5. Учтите высоту дерева

    Добавьте страницы внутренних узлов (1 корень, ветви).

  6. 6
    6. Проверьте через инструментарий СУБД

    MySQL: mysql.innodb_index_stats, Pg: pg_relation_size.

  7. 7
    7. Сравните с онлайн-калькулятором

    Используйте Калькулятор размера SQL индекса на сайте.

Для точной оценки пройдите шаги последовательно.

Влияние типа СУБД и настроек на размер

Разные СУБД и конфигурации меняют формулу:

ПараметрInnoDB (MySQL)PostgreSQL
Размер страницы16384 (16КБ, по умолчанию)8192 (8КБ, по умолчанию)
Размер указателя6 байт (на строку)6 байт (на строку)
Fill factor100% (нет незаполненного места)90% (10% свободно)
СжатиеКомпрессия страниц (KEY_BLOCK_SIZE)TOAST для больших значений, индексы не сжимаются
В PostgreSQL при fill_factor=90% мы должны делить число строк на страницу на 0.9: строк на страницу = 585 * 0.9 = 526, а количество страниц увеличивается на 11%.

Чек-лист перед созданием индекса

0 из 7

Как измерить реальный размер существующего индекса

Чтобы сверить расчёт с реальностью, используйте системные функции:

  • MySQL:
    SELECT SUM(stat_value * @@innodb_page_size) FROM mysql.innodb_index_stats WHERE database_name = 'db' AND table_name = 'users' AND index_name = 'idx_email' AND stat_name = 'size';

    Или проще:
    SELECT DATABASE_NAME, TABLE_NAME, INDEX_NAME, STAT_VALUE * @@innodb_page_size AS index_size_bytes FROM mysql.innodb_index_stats WHERE stat_name = 'size';
  • PostgreSQL:
    SELECT pg_size_pretty(pg_relation_size('idx_email'));

    Либо:
    SELECT relpages * 8192 AS index_size_bytes FROM pg_class WHERE relname = 'idx_email';

Для быстрой оценки используйте Калькулятор размера SQL индекса.

Подводные камни: фрагментация, включённые колонки, NULL

Фрагментация — после массовых вставок или обновлений страницы заполняются не полностью, увеличивая размер индекса на 20-30%. В InnoDB фрагментацию можно оценить через innodb_metrics.

Включённые колонки (INCLUDE в Pg, INCLUDE в MySQL 8.0+) добавляют в листовые страницы значения, не участвующие в поиске, но увеличивающие размер ключа. Например, если к индексу на id добавить email VARCHAR(255), размер листа вырастет.

NULL-значения — в InnoDB для индексов не хранится указатель на NULL, но в некоторых версиях MySQL не-NULL ключи занимают дополнительный бит (1 байт на колонку для nullable). В PostgreSQL NULL-ы хранятся в bitmap, что добавляет накладные расходы.

Частичные индексы (WHERE условие) — размер пропорционален числу строк, удовлетворяющих условию, а не всей таблицы.

Как сэкономить место: монотонные ключи и покрывающие индексы

  • Монотонные ключи (AUTO_INCREMENT, последовательные даты) — вставка происходит в конец, без разделения страниц. Размер меньше из-за отсутствия Page Split. В B-дереве отсутствуют пустые места.
  • Покрывающий индекс — если запрос выбирает только колонки, входящие в индекс, то читаются только листовые страницы. Размер индекса не меняется, но производительность выше.
  • Сжатие — InnoDB поддерживает компрессию страниц (ROW_FORMAT=COMPRESSED, KEY_BLOCK_SIZE), которая уменьшает размер в 2-3 раза, но требует CPU на сжатие/распаковку.

Онлайн-калькуляторы и утилиты для быстрого расчёта

Чтобы не считать вручную, используйте специализированные инструменты:

🧮 Посчитайте сами — инструменты по теме

🧭 Разделы по теме

Частые вопросы

Как размер индекса влияет на производительность запросов?

Большой индекс замедляет сканирование и увеличивает время на обновление при INSERT/UPDATE. Если индекс целиком влезает в оперативную память (Buffer Pool), то чтение быстрое. Если же он больше доступной памяти, подсистема будет читать с диска, что резко снижает скорость.

Что делать, если индекс занимает слишком много места?

Уменьшите количество колонок в индексе (оставьте только самые селективные). Рассмотрите частичный индекс с WHERE, если большинство запросов фильтруют по условию. Включите сжатие (InnoDB COMPRESSED формат). Для PostgreSQL используйте индекс типа BRIN на монотонных данных — он занимает намного меньше.

Отличается ли размер индекса для InnoDB и PostgreSQL?

Да. InnoDB использует 16 КБ страницы, Pg — 8 КБ. Fill factor по умолчанию 100% и 90% соответственно. Поэтому при прочих равных индекс в Pg будет примерно на 10-20% больше.

Как учесть NULL-значения в расчёте размера?

В InnoDB NULL-значения не занимают места в индексе, но каждый nullable столбец добавляет 1 байт к ключу. В PostgreSQL NULL-ы хранятся в битовой маске, что увеличивает накладные расходы. Для точной оценки лучше использовать онлайн-калькулятор с поддержкой nullable.

Почему реальный размер больше расчётного?

Из-за фрагментации, page header (около 100 байт на страницу), дополнительных структур (B-tree meta, internal pages). Реальный размер может быть на 10-30% больше. Для точной сверки используйте pg_relation_size/innodb_index_stats.

Сколько места сэкономит покрывающий индекс?

Сам индекс не меньше, но он может позволить не создавать отдельный индекс для покрытия. Экономия за счёт того, что один индекс заменяет несколько. Например, если часто ищете по user_id и получаете email — один покрывающий индекс на (user_id, email) может заменить два: на user_id и на email.

Нужно ли пересчитывать размер после реорганизации таблицы?

Да, после OPTIMIZE TABLE (InnoDB) или VACUUM FULL (Pg) размер индекса уменьшается из-за дефрагментации. Рекомендуется проводить операцию при значительных изменениях данных.

Есть ли онлайн-калькулятор размера SQL индекса?

Да, на нашем сайте: https://your-site.com/onlayn-kalkulyatory/dlya-programmistov/kalkulyator-razmera-sql-indeksa. Он считает с учётом типа СУБД, размера страницы, fill factor, типов данных.

Источники и нормативные документы

  1. MySQL InnoDB Index Documentation
  2. PostgreSQL B-tree Indexes
  3. Understanding InnoDB Index Page Structure

Ещё по теме «IT и код»