Что значит высокая утилизация базы данных и как с этим бороться?
Что проверяют
Понимаете ли вы, что за фразой «база загружена» стоит конкретный ресурс, и идёте ли от метрики к причине. Для Java-разработчика вопрос прикладной: чаще всего базу нагружает код приложения, а не нехватка железа.
Как отвечать
Сначала уточните, что именно утилизировано: процессор базы, диск по операциям и задержке, память под кэш страниц, соединения в пуле, ожидания на блокировках. Это разные болезни, и общий тезис «надо оптимизировать» без метрики ничего не значит.
Дальше диагностика: топ запросов по суммарному времени через статистику запросов или медленный лог, план проблемного запроса, число обращений к базе на один бизнес-вызов, время ожидания соединения из пула.
Типичные причины со стороны приложения:
N+1от ленивой загрузки в JPA: список сущностей превращается в сотни запросов, лечитсяjoin fetch, графом сущностей или батч-загрузкой;- отсутствие подходящего индекса, сортировка и соединение на диске;
- пагинация через большое смещение вместо выборки по ключу последней строки;
- вставки и обновления по одной записи без батчинга;
- длинные транзакции: держат блокировки и мешают чистке старых версий строк;
- раздутый пул соединений, который переносит очередь внутрь базы и усиливает конкуренцию.
После этого уже кэш горячих справочников, реплика под чтение, вынос отчётов из основной базы, шардирование как крайний шаг.
Где спотыкаются
Начинают с масштабирования. Реплика разгружает чтение, но не лечит лишние запросы и не ускоряет запись, а плохой план останется плохим и на более мощной машине.
Сводят утилизацию к процессору. Нередко всё упирается в диск или в ожидание блокировок, при этом процессор свободен, и оптимизация запросов вслепую не даёт ничего.
Считают, что пул соединений надо увеличивать. Сотня соединений к базе с несколькими ядрами ухудшает результат из-за переключений контекста и конкуренции за блокировки; размер пула подбирают под число ядер и профиль нагрузки, а не по принципу «побольше».