Какие архитектурные и эксплуатационные ограничения есть в PostgreSQL?

«Какие архитектурные и эксплуатационные ограничения есть в PostgreSQL?» — вопрос из категории Базы данных, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

PostgreSQL обладает высокими лимитами, но для проектирования систем важно знать ключевые ограничения.

Ограничения, связанные с размерами

  • Максимальный размер базы данных: Теоретически неограничен (на практике — до 32 ТБ для одной таблицы, что ограничивает общий размер).
  • Максимальный размер таблицы: 32 ТБ (при размере блока по умолчанию 8 КБ).
  • Максимальный размер строки: 1.6 ТБ. Практическое ограничение — размер блока (обычно 8 КБ). Строки с TOAST-able типами (как TEXT, JSONB) автоматически сжимаются и выносятся в отдельную область.
  • Максимальное количество столбцов в таблице: От 250 до 1600 в зависимости от типов данных.

Ограничения индексов

  • B-tree индекс: Максимальный размер ключа — 8191 байт (при блоке 8 КБ). Для больших ключей можно использовать hash индексы или выраженные индексы на части данных.
  • Составной индекс: Не более 32 столбцов.

Ограничения, связанные с производительностью и параллелизмом

  • Максимальное количество подключений: Задается параметром max_connections (по умолчанию 100). Каждое соединение потребляет ~10 МБ RAM, поэтому высокие значения требуют больших ресурсов.
  • Максимальное количество блокировок: Управляется параметром max_locks_per_transaction. Слишком малое значение может привести к ошибке "out of shared memory" в транзакциях, затрагивающих много таблиц.
  • Глубина рекурсии в CTE (WITH запросах): По умолчанию 100. Настраивается через max_recursive_iterations.

Пример, демонстрирующий ограничение на размер строки:

-- Создадим таблицу с большим текстовым полем
CREATE TABLE documents (
    id SERIAL PRIMARY KEY,
    content TEXT
);

-- Вставка очень большого текста НЕ вызовет ошибку,
-- так как PostgreSQL использует TOAST
INSERT INTO documents (content) VALUES (repeat('very long text ', 1000000));

-- Проверим, была ли строка сжата и вынесена
SELECT pg_column_size(content) as in_memory_size,
       pg_total_relation_size('documents') as table_size
FROM documents;
-- in_memory_size будет небольшим (~1KB), а table_size покажет реальный вес.

Практический совет: Основные «узкие места» в PostgreSQL обычно связаны не с этими лимитами, а с неправильной настройкой work_mem, shared_buffers, отсутствием индексов или блокировками.