Материал не актуален, не используется. Перенесён в архив.
Чистый OLTP (< 10:1, часто 2:1 - 5:1)
Характеристика: интенсивные короткие транзакции с высокой конкуренцией за данные
Паттерн: каждая транзакция читает немного данных (обычно по индексам) и часто изменяет записи
Смешанная нагрузка (HTAP) (10:1 - 100:1)
Характеристика: сочетание оперативных транзакций и аналитических запросов
Паттерн: чтений значительно больше, чем записей, но запись происходит регулярно
Классический OLAP (> 100:1, может достигать 1000:1 и выше)
Характеристика: доминирование сложных аналитических запросов
Паттерн: массовое сканирование больших объёмов данных с редкой пакетной записью
Система только для чтения (→ ∞, деление на ноль)
Характеристика: полное отсутствие операций записи
Паттерн: shared_blks_dirtied = 0 или крайне мало
Важное уточнение:
Эти диапазоны следует рассматривать как ориентировочные.
Фактическая классификация должна учитывать:
- Абсолютные значения (1000:1 при 1000 прочитанных блоках ≠ 100:1 при 10M блоков)
- Временные паттерны (соотношение меняется в течение суток)
- Дополнительные метрики (TPS, процент последовательных сканирований, конкурентность)
Для классификации рабочей нагрузки не существует общепринятых стандартных граничных абсолютных значений для суммы shared_blks_hit + shared_blks_read. Абсолютные цифры (например, "100,000 прочитанных блоков") сами по себе не информативны, поскольку полностью зависят от размера конкретной базы данных, объема данных и масштаба операций.
📏 Критерии для осмысленного анализа
Чтобы оценить нагрузку, абсолютные значения нужно сравнивать с контекстом вашей системы. Предлагаю структуру анализа на основе сопоставления метрик с общим объемом данных.
Классификация на основе относительных показателей:
- OLTP (оперативная обработка): Обработка отдельных записей (по WHERE id = ?). Значительная часть операций (shared_blks_hit) приходится на кеш. Высокое значение shared_blks_dirtied относительно shared_blks_read.
- OLAP (аналитическая обработка): Агрегация по большим массивам данных (например, GROUP BY, оконные функции). Большое количество shared_blks_read и shared_blks_hit. Низкое значение shared_blks_dirtied.
- Высокая нагрузка (проблемная): shared_blks_read чрезмерно высок относительно общего размера базы. Низкий процент попаданий в кеш (shared_blks_hit). Система постоянно читает с диска.
🔍 Практический метод оценки
Для осмысленной оценки нагрузки по абсолютным значениям можно использовать следующий запрос, который добавляет контекст размера базы данных:
WITH db_stats AS (
SELECT
datname,
-- Суммарный объем прочитанных блоков
SUM(shared_blks_hit + shared_blks_read) AS total_blocks_accessed,
-- Суммарный объем измененных блоков
SUM(shared_blks_dirtied) AS total_blocks_dirtied,
-- Расчет отношения
CASE
WHEN SUM(shared_blks_dirtied) > 0
THEN ROUND(SUM(shared_blks_hit + shared_blks_read)::numeric / SUM(shared_blks_dirtied), 2)
ELSE NULL
END AS read_to_dirtied_ratio
FROM pg_stat_statements pss
JOIN pg_database pd ON pss.dbid = pd.oid
GROUP BY datname
),
size_stats AS (
-- Подзапрос для оценки общего размера данных в базах (в блоках по 8KB)
SELECT
datname,
-- Примерная оценка размера данных (требует доработки под вашу схему)
(SELECT SUM(pg_total_relation_size(oid)) / 8192
FROM pg_class
WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'public')
) AS estimated_blocks
FROM pg_database
WHERE datname NOT LIKE 'template%'
)
SELECT
ds.datname,
ds.total_blocks_accessed,
ds.total_blocks_dirtied,
ds.read_to_dirtied_ratio,
ss.estimated_blocks,
-- Ключевой показатель: какой процент от общего объема данных был прочитан?
CASE
WHEN ss.estimated_blocks > 0
THEN ROUND((ds.total_blocks_accessed::numeric / ss.estimated_blocks * 100)::numeric, 4)
ELSE NULL
END AS percent_of_db_accessed,
-- Грубая классификация на основе процента
CASE
WHEN ds.total_blocks_dirtied = 0 THEN 'READ_ONLY'
WHEN (ds.total_blocks_accessed::numeric / ss.estimated_blocks) > 0.5 THEN 'POTENTIAL_OLAP'
WHEN ds.read_to_dirtied_ratio < 10 THEN 'POTENTIAL_OLTP'
ELSE 'MIXED'
END AS workload_hint
FROM db_stats ds
LEFT JOIN size_stats ss ON ds.datname = ss.datname
WHERE ds.datname IS NOT NULL
ORDER BY ds.total_blocks_accessed DESC;
Как интерпретировать результат:
- percent_of_db_accessed: Прочитано 50% и более от общего объема данных за период? Это указывает на аналитическую (OLAP) нагрузку.
- workload_hint: Автоматическая подсказка на основе порогов, требует проверки на ваших данных.
💡 Рекомендации по использованию метрик
Комбинируйте метрики: Отношение чтения/записи — лишь один индикатор. Важны также:
- blk_read_time / blk_write_time: фактическое время ввода-вывода.
- Среднее время выполнения запроса (mean_exec_time).
- Количество строк, обработанных за вызов (rows/calls).
📚 Источники
- Официальная документация PostgreSQL по pg_stat_statements — первичный источник, описывающий все столбцы, включая shared_blks_hit, shared_blks_read и shared_blks_dirtied.
- Статья "Understanding PostgreSQL Query Performance" от pgDash — объясняет, как интерпретировать показатели блоков для анализа производительности запросов.
- Блог "Queries for pg_stat_statements" от pgMustard — содержит практические примеры запросов для анализа нагрузки через статистику буферов.
Ваш вопрос затрагивает интересную область, где универсальных стандартов нет, но есть устоявшаяся практика анализа через контекст и относительные показатели. Используя предложенный метод, вы сможете выявить реальные паттерны нагрузки именно в вашей системе.