Меню
Онлайн-инструментОнлайнБесплатно

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

Калькулятор размера SQL индекса позволяет быстро оценить размер индекса в PostgreSQL и MySQL по количеству строк, типу данных и структуре индекса. Выберите тип данных, укажите количество строк и получите результат за 10 секунд без формул.

Обновлено: 15 мая 2026 г.
ФормулыБыстроПриватно

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

Оцените примерный размер индекса в PostgreSQL/MySQL на основе количества строк, типа данных и структуры индекса — за 10 секунд без формул.

Примерный размер индекса
Количество страниц (8 КБ)
страниц
Размер на одну запись
байт
Записей на странице
шт.

Как пользоваться калькулятором

1
Укажите количество строк в таблице — например, 500 000 для средней таблицы интернет-магазина.
2
Выберите тип данных столбца из списка. Для VARCHAR(50) размер составит 54 байта (50 символов + 4 байта служебной информации). Если вашего типа нет — выберите «Свой размер» и укажите точное значение в байтах.
3
Выберите тип индекса и настройте fillfactor. По умолчанию B-tree с fillfactor 90% — стандарт для PostgreSQL. Для составного индекса укажите количество столбцов.
4
Нажмите «Рассчитать». Результат покажет примерный размер индекса в удобных единицах, количество страниц и другие метрики. Сравните с реальным размером через pg_total_relation_size().

Примеры расчёта

Индекс на BIGINT для 10 млн строк
Исходные данные: 10 000 000 строк, BIGINT (8 байт), B-tree, fillfactor 90%, 1 столбец. Результат: ~346 МБ. Расчёт: размер записи 20 байт, на странице ~332 записи, ~30 120 страниц.
Составной индекс на VARCHAR(100) + DATE
Исходные данные: 2 000 000 строк, VARCHAR(100) — 104 байта + DATE — 4 байта = 108 байт ключ, B-tree, fillfactor 90%, 2 столбца. Результат: ~314 МБ. Размер записи 120 байт, на странице ~61 запись, ~32 786 страниц.
BRIN-индекс на TIMESTAMP для 100 млн строк
Исходные данные: 100 000 000 строк, TIMESTAMP (8 байт), BRIN, fillfactor 90%, 1 столбец. Результат: ~3,2 МБ. BRIN чрезвычайно компактен — всего ~388 страниц благодаря диапазонному хранению.

Формулы расчёта

Калькулятор использует следующую математическую модель, основанную на внутреннем устройстве страниц PostgreSQL (8 КБ):

размер_ключа = размер_столбца × количество_столбцов
размер_записи = размер_ключа + overhead_типа_индекса + 4 (указатель CTID)
полезное_место_на_странице = (8192 − 28) × fillfactor / 100
записей_на_странице = ⌊полезное_место_на_странице / размер_записи⌋ (минимум 1)
количество_страниц = ⌈количество_строк / записей_на_странице⌉
размер_индекса = количество_страниц × 8192 байт

Overhead по типам индексов: B-tree — 8 байт, Hash — 4 байта, GiST — 16 байт, GIN — 20 байт, BRIN — 8 байт (плюс 4 байта CTID-указателя для каждого). Заголовок страницы — 28 байт (PageHeaderData).

Пошаговое объяснение

Расчёт проходит в четыре этапа. Сначала определяется размер ключа — сумма байтовых размеров всех столбцов индекса. Для VARCHAR(N) это N + 4 байта (4 байта хранят фактическую длину строки), для INT — ровно 4 байта.

Затем добавляется overhead типа индекса. B-tree требует 8 байт на внутренние указатели дерева плюс 4 байта на CTID (физический адрес строки в куче). GiST и GIN имеют больший overhead из-за сложной внутренней структуры.

На третьем этапе вычисляется ёмкость страницы. Стандартный блок PostgreSQL — 8192 байта. Вычитаем 28 байт заголовка, умножаем на fillfactor. Получаем полезное пространство, доступное для записей индекса.

Наконец, определяется количество страниц делением общего числа строк на количество записей на странице с округлением вверх. Умножение на 8192 даёт итоговый размер индекса в байтах.

Где применяется

  • Планирование дискового пространства — оценка размера индексов перед созданием новой таблицы или миграцией, чтобы зарезервировать достаточно места на SSD/HDD.
  • Оптимизация производительности — понимание, поместится ли индекс в оперативную память (shared_buffers). Индекс, целиком попадающий в кеш, работает в разы быстрее.
  • Сравнение типов индексов — выбор между B-tree и BRIN для хронологических данных. BRIN может быть в 100 раз компактнее на миллиардах строк.
  • Аудит существующей базы — расчёт ожидаемого размера и сравнение с реальным через pg_total_relation_size() для выявления раздувания (bloat).
  • Проектирование составных индексов — оценка стоимости добавления ещё одного столбца в индекс: каждый дополнительный столбец увеличивает размер записи и общий размер индекса.
  • Облачные затраты — в AWS RDS или Google Cloud SQL размер индексов напрямую влияет на счёт за хранилище. Точная оценка помогает избежать перерасхода.

Важные нюансы

  • Оценка, а не точное значение. Реальный размер зависит от множества факторов: сжатие TOAST, выравнивание данных, фрагментация после UPDATE и DELETE. Калькулятор даёт оценку с погрешностью ±10-15%.
  • NULL-значения не занимают место в индексе (для B-tree). Если 80% строк имеют NULL в индексируемом столбце, реальный размер индекса будет значительно меньше расчётного. Учитывайте долю NULL при оценке.
  • Fillfactor ниже 100% ускоряет INSERT, но увеличивает размер. Значение 70% означает, что 30% каждой страницы резервируется под будущие вставки — индекс будет физически больше, но избежит дорогостоящих расщеплений страниц.
  • Для VARCHAR учитывайте фактическую среднюю длину. Если столбец объявлен как VARCHAR(255), но средняя длина строки — 20 символов, используйте в расчётах 24 байта (20+4), а не 259. Это даст гораздо более точный результат.
  • GIN-индексы могут быть неожиданно большими. Один массив из 10 элементов в GIN порождает 10 отдельных записей в индексной таблице. Для массивов и JSONB реальный размер GIN-индекса может превышать размер самой таблицы.
  • BRIN работает иначе. Он хранит диапазоны значений для блоков страниц, а не отдельные строки. Размер BRIN-индекса почти не зависит от количества строк — только от количества блоков таблицы и параметра pages_per_range.

Частые ошибки

  • Путаница байтов и символов. VARCHAR(100) в UTF-8 может занимать до 400 байт на строку (кириллица — 2 байта на символ, эмодзи — 4). Калькулятор считает в байтах. Убедитесь, что переводите символы в байты корректно.
  • Игнорирование составных индексов. Индекс на (city, street, house) — это не три отдельных индекса, а один с суммарным размером ключа. Ошибка: считать размер каждого столбца отдельно и складывать размеры трёх разных индексов.
  • Завышенные ожидания от fillfactor=100%. Полностью заполненные страницы быстро фрагментируются при любых вставках. Для активно обновляемых таблиц fillfactor=100% приводит к падению производительности и раздуванию индекса.
  • Пренебрежение overhead-ом. Разница между 8 байтами ключа и 20 байтами записи индекса (с overhead) — это 2,5-кратная разница в размере. Новички часто забывают про CTID и внутренние указатели.
  • Расчёт на пиковое количество строк без запаса. Если таблица вырастет с 1 млн до 5 млн строк, индекс вырастет пропорционально. Закладывайте запас 20-30% при планировании дискового пространства.
  • Использование одного типа индекса для всех задач. B-tree — универсальный, но неоптимальный для полнотекстового поиска (нужен GIN) или геоданных (нужен GiST). Ошибка выбора типа индекса ведёт к неадекватному размеру и низкой производительности.

Ответы на частые вопросы

Почему мой реальный индекс больше расчётного? Скорее всего, в таблице много «мёртвых» строк после UPDATE/DELETE, и индекс раздут. Выполните VACUUM или REINDEX для восстановления размера. Также проверьте актуальность статистики через ANALYZE.

Какой fillfactor выбрать для таблицы с частыми вставками? Для активно пополняемых таблиц (логи, события) рекомендуем fillfactor 70-80%. Это замедлит рост индекса и уменьшит фрагментацию. Для статических архивных таблиц можно использовать 100%.

BRIN или B-tree для временных рядов? Для данных, где строки вставляются последовательно по времени (события, метрики), BRIN даёт выигрыш по размеру в 50-200 раз при сопоставимой скорости чтения диапазонов. B-tree оправдан, если нужны точечные запросы.

Сколько столбцов можно включать в составной индекс? Технически — до 32, практически — не более 5-7. Каждый дополнительный столбец увеличивает размер индекса и замедляет вставки. Составной индекс на 10 столбцов размером с таблицу — это антипаттерн.

Влияет ли порядок столбцов в составном индексе на размер? На размер — нет. Сумма байтов та же. Но порядок критичен для производительности: индекс используется только если условия в WHERE начинаются с первого столбца индекса (правило левого префикса).

Можно ли использовать калькулятор для MySQL? Да, с оговорками. MySQL/InnoDB использует страницы по 16 КБ (вместо 8 КБ) и кластерный индекс (PRIMARY KEY включён во все вторичные индексы). Для MySQL умножайте результат на 1,5-2 для вторичных индексов.

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

Расчёт основан на официальной документации PostgreSQL (раздел «Database Page Layout», статьи 68.1-68.4), исходном коде PostgreSQL (файл bufpage.h, структура PageHeaderData — 24 байта + 4 байта выравнивания = 28 байт), а также исследованиях производительности индексов (Use The Index, Luke!). Overhead для B-tree взят из статьи «B-tree index internals» (PostgreSQL Wiki), для GiST/GIN — из документации PostgreSQL, раздел «GiST Indexes» и «GIN Indexes». Размеры типов данных соответствуют pg_type.typlen и документации по типам данных PostgreSQL 16.

SQL-индексы и их размер: полное практическое руководство

Зачем вообще знать размер индекса?

Индекс — это отдельная структура данных, которая физически хранится на диске рядом с таблицей. Каждый созданный индекс занимает место, иногда сопоставимое с размером самой таблицы. На проекте с 50 таблицами и 200 индексами суммарный размер индексов может превышать 500 ГБ — и это напрямую влияет на стоимость хранения в облаке и время бэкапов.

Знание примерного размера индекса до его создания помогает ответить на три вопроса: хватит ли дискового пространства, поместится ли индекс в оперативную память сервера и стоит ли вообще его создавать или лучше обойтись частичным индексом. Практика показывает, что 15-20% индексов в продуктовых базах либо не используются, либо дублируют друг друга.

Как устроена страница индекса в PostgreSQL

PostgreSQL хранит индексы в виде страниц фиксированного размера — 8192 байта (8 КБ). Это минимальная единица чтения и записи. Каждая страница содержит заголовок (28 байт), массив указателей на записи и сами записи индекса. Свободное пространство между записями и концом страницы используется для будущих вставок.

Когда новая строка попадает в индекс, PostgreSQL ищет подходящую страницу и размещает запись там. Если свободного места недостаточно, страница расщепляется на две — это дорогая операция, которая блокирует запись и увеличивает размер индекса. Fillfactor как раз управляет тем, сколько места резервируется под будущие вставки.

Для B-tree индекса каждая запись содержит: значение ключа (ваши данные), CTID — указатель на физическое расположение строки в таблице (6 байт: номер блока + смещение), и служебные биты для навигации по дереву (ещё 2-4 байта). Суммарно overhead составляет 8-12 байт на запись.

Пять типов индексов и их особенности

B-tree — универсальный тип, покрывающий 90% потребностей. Поддерживает операции =, <, >, BETWEEN, ORDER BY. Размер линейно зависит от количества строк. Overhead: ~12 байт на запись.

Hash — работает только для точного сравнения (=). Компактнее B-tree на 15-20% за счёт меньшего overhead (~8 байт). Хорош для первичных ключей-суррогатов, если не нужна сортировка. В PostgreSQL до версии 10 Hash-индексы не журналировались и считались небезопасными — сейчас это полноценный тип.

GiST — обобщённое поисковое дерево. Используется для геоданных (PostGIS), полнотекстового поиска и пользовательских типов. Overhead: ~20 байт на запись. Размер может быть в 1,5-2 раза больше B-tree на тех же данных из-за сложных внутренних структур.

GIN — инвертированный индекс. Идеален для массивов, JSONB и полнотекстового поиска. Каждый элемент массива или каждый токен документа порождает отдельную запись в индексе, поэтому размер GIN-индекса может многократно превышать размер таблицы. Overhead: ~24 байта на запись.

BRIN — блочный диапазонный индекс. Хранит не отдельные строки, а диапазоны значений для групп страниц (по умолчанию 128 страниц в группе). Чрезвычайно компактный: индекс на 100 млн строк может занимать 3-5 МБ. Подходит только для данных с физической корреляцией (временные ряды, автоинкрементные ID).

Практические советы по управлению размером индексов

Всегда проверяйте, используется ли индекс. Запрос SELECT * FROM pg_stat_user_indexes WHERE idx_scan = 0 показывает индексы, которые ни разу не использовались с момента сброса статистики. Такие индексы — кандидаты на удаление.

Рассмотрите частичные индексы. Вместо индекса на всю таблицу создайте индекс с WHERE-условием: CREATE INDEX idx_active ON orders(status) WHERE status = 'active'. Если активных заказов 5% от общего числа, индекс будет в 20 раз меньше полного.

Для TIMESTAMP и автоинкрементных ID используйте BRIN. Таблица логов с 500 млн строк и B-tree индексом на timestamp требует ~12 ГБ диска. BRIN-индекс на том же столбце — всего 40-60 МБ, а производительность выборки за конкретный день сопоставима.

Мониторьте раздувание (bloat). После интенсивных UPDATE и DELETE индекс может занимать в 2-3 раза больше своего «чистого» размера. Расширение pgstattuple и запросы на основе pg_class помогают выявить раздутые индексы. Регулярный REINDEX CONCURRENTLY возвращает размер к норме без блокировки записи.

Кейс: оптимизация индексов в интернет-магазине

Средний интернет-магазин имеет таблицу orders на 5 млн строк. Индексы: PRIMARY KEY (id) — 214 МБ, индекс на customer_id — 168 МБ, индекс на created_at — 156 МБ, составной индекс на (status, created_at) — 245 МБ. Итого: 783 МБ только на индексы одной таблицы.

После аудита выяснилось, что индекс на customer_id используется только в админке (0,1% запросов), а составной индекс дублирует created_at на 80%. Решение: удалить индекс на customer_id, заменить составной на частичный WHERE status IN ('pending','processing'). Итог: 783 → 420 МБ, экономия 363 МБ на одной таблице.

Заключение

Размер индекса — это не абстрактная цифра, а прямой фактор стоимости владения базой данных. Один непродуманный индекс на большую таблицу может стоить десятки гигабайт диска и тысячи рублей ежемесячно в облачном тарифе. Используйте калькулятор на этой странице для быстрой оценки, сравнивайте типы индексов и не создавайте индексы «на всякий случай». Помните: каждый индекс ускоряет чтение, но замедляет запись и занимает место. Баланс — ключ к эффективной работе с SQL.

Спросить у ИИ

Задайте вопрос по этому калькулятору

Осталось вопросов: 5. Только по этому инструменту.

Оцените калькулятор

Нужен другой инструмент?

Все инструменты в категории