[Документация Yandex Cloud](../../index.md) > [Практические руководства](../index.md) > [Построение Data Platform](index.md) > Анализ производительности и оптимизация Yandex StoreDoc

# Анализ производительности и оптимизация MongoDB

# Анализ производительности и оптимизация Yandex StoreDoc


{% note warning %}

Часть ресурсов, необходимых для прохождения практического руководства, доступны только в [регионе Россия](../../overview/concepts/region.md).

{% endnote %}


В этом руководстве вы узнаете:

* как использовать [инструменты диагностики производительности](../../storedoc/operations/tools.md) и [мониторинга](../../storedoc/operations/monitoring.md);
* как устранять обнаруженные проблемы.

Снижение производительности кластера Yandex StoreDoc чаще всего происходит по одной из следующих причин:

* [высокая утилизация CPU и дискового I/O](#cpu-io-deficit),
* [неэффективное выполнение запросов в Yandex StoreDoc](#inefficient-queries),
* [блокировки](#locks),
* [недостаток дискового пространства](#disk-deficit).

Ниже приводятся советы по диагностике и решению этих проблем.

## Перед началом работы {#before-start}

1. Установите на внешнем хосте, имеющем сетевой доступ к хосту Yandex StoreDoc (смотрите [Предварительная настройка для подключения к кластеру Yandex StoreDoc](../../storedoc/operations/connect/index.md)), [утилиты](../../storedoc/operations/tools.md#monitoring-tools) получения данных о производительности Yandex StoreDoc `mongostat` и `mongotop`.
1. Определите, для каких баз данных нужно выявить проблемы.
1. [Создайте пользователя](../../storedoc/operations/cluster-users.md#adduser) Yandex StoreDoc с ролью [`mdbMonitor`](../../storedoc/concepts/users-and-roles.md#mdbMonitor) для этих баз. Это необходимо для использования утилит `mongostat` и `mongotop`.

## Диагностика дефицита ресурсов {#cpu-io-deficit}

Если какой-то из ресурсов CPU и дискового I/O «вышел на плато» — постоянно росший до этого момента [график](../../storedoc/operations/monitoring.md) остановился на одном уровне — скорее всего, соответствующий ресурс стал дефицитным и это привело к падению производительности. Чаще всего это происходит потому, что использование ресурса достигло [лимита](../../storedoc/concepts/limits.md).

В большинстве случаев высокая утилизация CPU и высокие Disk IO связаны с неоптимальными индексами или большой нагрузкой на хосты.

Начните диагностику с выяснения характера нагрузки и определения проблемных коллекций. Воспользуйтесь встроенными [утилитами мониторинга Yandex StoreDoc](../../storedoc/operations/tools.md#monitoring-tools). Далее проанализируйте производительность конкретных запросов с помощью [логов](../../storedoc/operations/tools.md#explore-logs) или [данных профилировщика](../../storedoc/operations/tools.md#explore-profiler).

Обратите внимание на запросы:

* Не использующие индексы (`planSummary: COLLSCAN`). Такие запросы могут увеличивать как потребление I/O (чтений с диска будет больше), так и CPU (данные сжаты по умолчанию, для них требуется декомпрессия). Если необходимый индекс есть, но БД его не использует, можно форсировать использование индекса с помощью `hint`.
* С большими значениями параметра `docsExamined` (количества просканированных документов). Это может означать, что текущие индексы неэффективны или требуются дополнительные.

В момент падения производительности проблему можно диагностировать в реальном времени с помощью [списка текущих запросов](../../storedoc/operations/tools.md#list-running-queries):

{% list tabs %}

- Запросы всех пользователей

    Для выполнения таких запросов пользователь должен обладать [ролью `mdbMonitor`](../../storedoc/concepts/users-and-roles.md#mdbMonitor).

    * Долгие запросы, например, исполняющиеся более секунды:

      ```javascript
      db.currentOp({"active": true, "secs_running": {"$gt": 1}})
      ```

    * Запросы по созданию индексов:

      ```javascript
      db.currentOp({ $or: [{ op: "command", "query.createIndexes": { $exists: true } }, { op: "none", ns: /\.system\.indexes\b/ }] })
      ```

- Запросы текущего пользователя

    * Долгие запросы, например, исполняющиеся более секунды:

      ```javascript
      db.currentOp({"$ownOps": true, "active": true, "secs_running": {"$gt": 1}})
      ```

    * Запросы по созданию индексов:

      ```javascript
      db.currentOp({ "$ownOps": true, $or: [{ op: "command", "query.createIndexes": { $exists: true } }, { op: "none", ns: /\.system\.indexes\b/ }] })
      ```

{% endlist %}


## Устранение проблем с дефицитом ресурсов {#solving-deficit}

[Попробуйте оптимизировать](#optimize) найденные запросы. Если нагрузка все еще высокая или оптимизировать нечего, остается только [поднять класс хостов](../../storedoc/operations/update.md#change-resource-preset).

## Диагностика неэффективного выполнения запросов {#inefficient-queries}

Чтобы выявить проблемные запросы в Yandex StoreDoc:

* Изучите [логи](../../storedoc/operations/tools.md#explore-logs). Особое внимание обратите:

   * Для запросов на чтение — на поле `responseLength` (в логах отображается как `reslen`).
   * Для запросов на запись — на количество затронутых документов.
       В логах кластера они выводятся в полях `nModified`, `keysInserted`, `keysDeleted`. На странице [мониторинга кластера](../../storedoc/operations/monitoring.md#cluster) изучите графики **Documents affected on primary**, **Documents affected on secondaries**, **Documents affected per host**.
* Изучите данные [профилировщика](../../storedoc/operations/tools.md#explore-profiler). Выведите долго выполняемые запросы (регулируется [настройкой СУБД `slowOpThreshold`](../../storedoc/concepts/settings-list.md#setting-slow-op-threshold)).

## Устранение проблем с неэффективными запросами {#optimize}

Каждый отдельный запрос можно проанализировать с точки зрения его плана (query plan).

Изучите графики на странице [мониторинга кластера](../../storedoc/operations/monitoring.md#cluster):

* **Index size on primary, top 5 indexes**,
* **Scan and order per host**,
* **Scanned / returned**.

Для ускорения выборок используйте индексы.

{% note warning %}

Каждый новый индекс замедляет запись. Большое количество индексов может негативно влиять на производительность при записи.

{% endnote %}

Чтобы оптимизировать запросы на чтение, используйте частичное извлечение (projection). Во многих случаях доставать документ целиком не нужно, достаточно нескольких его полей.

Если не удается ни оптимизировать найденные запросы, ни отказаться от них, [поднимите класс хостов](../../storedoc/operations/update.md#change-resource-preset).

## Диагностика наличия блокировок (locks) {#localize-locking-issues}

Причиной низкой производительности запросов могут быть блокировки (locks).

Yandex StoreDoc не предоставляет подробной информации по блокировкам. В частности, есть только косвенные способы узнать, чем заблокирован конкретный запрос:

* Обратите внимание на большие или растущие значения `db.serverStatus().metrics.operation.writeConflicts` — они могут говорить о высоком write contention на каких-то документах.

* Изучите большие или растущие значения на графике **Write conflicts per hosts** на странице [мониторинга кластера](../../storedoc/operations/monitoring.md#cluster).

* В момент падения производительности внимательно изучите [список текущих запросов](../../storedoc/operations/tools.md#list-running-queries):

    {% list tabs %}

    - Запросы всех пользователей

        Для выполнения таких запросов пользователю необходима [роль `mdbMonitor`](../../storedoc/concepts/users-and-roles.md#mdbMonitor).

        * Найдите запросы, которые удерживают эксклюзивные блокировки, например:

          ```javascript
          db.currentOp({'$or': [{'locks.Global': 'W'}, {'locks.Database': 'W'}, {'locks.Collection': 'W'} ]}).inprog
          ```

        * Найдите запросы, ожидающие блокировок (в поле `timeAcquiringMicros` будет видно время ожидания):

          ```javascript
          db.currentOp({'waitingForLock': true}).inprog
          db.currentOp({'waitingForLock': true, 'secs_running' : { '$gt' : 1 }}).inprog
          ```

    - Запросы текущего пользователя

        * Найдите запросы, которые удерживают эксклюзивные блокировки, например:

          ```javascript
          db.currentOp({"$ownOps": true, '$or': [{'locks.Global': 'W'}, {'locks.Database': 'W'}, {'locks.Collection': 'W'} ]}).inprog
          ```

        * Найдите запросы, ожидающие блокировок (в поле `timeAcquiringMicros` будет видно время ожидания):

          ```javascript
          db.currentOp({"$ownOps": true, 'waitingForLock': true}).inprog
          db.currentOp({"$ownOps": true, 'waitingForLock': true, 'secs_running' : { '$gt' : 1 }}).inprog
          ```

    {% endlist %}

* В [логах](../../storedoc/operations/tools.md#explore-logs) и [профилировщике](../../storedoc/operations/tools.md#explore-profiler) обратите внимание на следующее:
  * запросы, долго ожидавшие получения блокировок, будут иметь большие значения `timeAcquiringMicros`;
  * запросы, которые конкурировали за одни и те же документы, будут иметь большие значения `writeConflicts`.


## Устранение проблем с блокировками {#solve-locks}

Найденные блокировки указывают на неоптимизированные запросы. Попробуйте [оптимизировать проблемные запросы](#optimize).

## Диагностика недостатка дискового пространства {#disk-deficit}

Если кластер демонстрирует низкую производительность в сочетании с малым объемом свободного дискового пространства, возможно, для одного или нескольких хостов кластера [активировался режим <q>только чтение</q>](../../storedoc/concepts/storage.md#manage-storage-space).

Объем занятого пространства в хранилище отображается на странице [мониторинга кластера](../../storedoc/operations/monitoring.md#cluster) на графиках **Disk space usage per host, top 5 hosts**.

Чтобы отслеживать степень заполнения хранилища на хостах кластера, [настройте алерт](../../storedoc/operations/monitoring.md#read-only-alert).

## Устранение проблем с дисковым пространством {#solve-disk-deficit}

Рекомендации по устранению проблем приведены в разделе [Поддержка работоспособности кластера](../../storedoc/concepts/storage.md#read-only-solutions).