---
metadata:
  - name: generator
    content: Diplodoc Platform v5.50.6
alternate:
  - https://ytsaurus.tech/docs/en/yql/faq/performance.md
  - https://ytsaurus.tech/docs/ru/yql/faq/performance.md
---
> **Documentation Index:** Fetch the complete configuration index at https://ytsaurus.tech/docs/ru/llms.txt

# Производительность

## Почему так долго работает запрос с JOIN? {#perf_join}

Все основные виды [JOIN](https://ytsaurus.tech/docs/ru/yql/syntax/join.md) (кроме SEMI/ONLY) строят декартово произведение строк по совпадающим значениям ключей. Если одно или несколько значений ключа являются особенными, то по нему может оказаться большое число строк с каждой из сторон и, как следствие, гигантское декартово произведение. В большинстве случаев JOIN работает медленно именно из-за этого, а такие особые значения с прикладной точки зрения оказываются не так интересны, и достаточно их исключить в `WHERE`.

Найти аномально часто встречающиеся значения можно с помощью двух запросов по каждой из таблиц с GROUP BY по тем же ключам, что и у `JOIN`, используя агрегатную функцию `COUNT` и убывающую сортировку по её результату. Ещё можно добавить `LIMIT 100`, чтобы отработало ещё быстрее.

Также бывают запросы, где на самом деле декартово произведение в `JOIN` не нужно, т. к. потом всё равно от значений тем или иным способом оставляют только уникальные значения. В этом случае стоит убрать дубли в подзапросе через [GROUP BY](https://ytsaurus.tech/docs/ru/yql/syntax/group_by.md) или [SELECT DISTINCT](https://ytsaurus.tech/docs/ru/yql/syntax/select/distinct.md) ещё до `JOIN`.

## Мой запрос раньше работал за N часов, а теперь стал работать за M часов. В чем причина? {#perf_slowdown}

При анализе производительности стоит обратить внимание на следующие моменты:

### Поменялся ли входной объём данных

 Например, в запрос стало попадать больше таблиц или существенно изменился их объём. Чтобы проверить, поменялся ли входной объём данных, можно кликнуть в плане запроса на первую YTsaurus операцию и посмотреть в интерфейсе YTsaurus на `Data flow`/`Data weight`:

![](../../../images/data_weight.png)

### Поменяли ли план исполнения запроса

Если план изменился, то это могло произойти по нескольким причинам:
* Стала применяться другая стратегия `JOIN`. Про критерии срабатывания той или иной стратегии смотри [отдельную статью](https://ytsaurus.tech/docs/ru/yql/syntax/join.md#join_strategy).
* Изменилась схема некоторых входных таблиц в папке. YQL выравнивает схему входных таблиц, что приводит к появлению дополнительных операций.
* Поменялись оптимизаторы YQL с релизом новой версии.

### Используется ли в запросе пул с выделенными гарантиями

В запросе должна быть указана прагма [yt.StaticPool](https://ytsaurus.tech/docs/ru/yql/syntax/pragma/yt.md#ytstaticpool) для применения пула. Если её нет, то время исполнения запроса никак не гарантируется. На него могут повлиять как соседние запросы, так и сезонные колебания нагрузки на кластера (перед ревью нагрузка на кластера, как правило, возрастает). Также стоит убедиться, что пул задаётся прагмой [yt.StaticPool](https://ytsaurus.tech/docs/ru/yql/syntax/pragma/yt.md#ytstaticpool), а не [yt.Pool](https://ytsaurus.tech/docs/ru/yql/syntax/pragma/yt.md#ytpool). Последняя является динамической прагмой, применяемой уже в рантайме. Из-за этого служебные операции, запущенные на этапе оптимизации, не используют её значение и запускаются в пуле по умолчанию, что может приводить к их существенному замедлению. Прагма [yt.StaticPool](https://ytsaurus.tech/docs/ru/yql/syntax/pragma/yt.md#ytstaticpool) применяется для всех операций, в том числе и служебных.

### Проверка суммарных статистик запроса

На вкладке `Statistics` YQL-запроса можно посмотреть его суммарные статистики:
![](../../../images/stat.png)

Здесь в первую очередь нужно обратить внимание и сравнить значения следующих статистик:
* `yt/total/Job_CalcTime` (Sum) &mdash; полезное время, проведенное во всех джобах с пользовательским кодом всех YTsaurus-операций запроса. Изменение этого значения при отсутствии изменения входного объёма данных говорит об изменениях производительности в YQL-рантайме.
* `yt/total/Job_InputDecodeTime` (Sum) &mdash; время, потраченное YQL декодером на чтение входных данных во всех джобах всех YTsaurus-операций запроса. Изменение этого значения при отсутствии изменения входного объёма данных говорит об изменениях производительности в YQL декодере.
* `yt/total/Job_OutputEncodeTime` (Sum) &mdash; время, потраченное YQL энкодером на запись данных во всех джобах всех YTsaurus-операций запроса. Изменение этого значения при отсутствии изменения входного объёма данных говорит об изменениях производительности в YQL энкодере.
* `yt/total/CodeGen_FullTime` (Sum) &mdash; время, потраченное на кодогенерацию во всех джобах всех YTsaurus-операций запроса. Изменение этого значения при том же числе YTsaurus-джобов говорит об изменениях производительности кодогенерации YQL-рантайма. Если это время составляет существенную долю от `Job_CalcTime`, то стоит рассмотреть вариант отключения LLVM в запросе через `pragma config.flags("LLVM", "OFF")`.
* `yt/total/Join_Spill_Count` (Sum) &mdash; ненулевое значение этой статистики говорит о проблемах производительности `JOIN` в запросе. Если ключи по первой стороне джойна имеют очень много записей, то они не помещаются в памяти и сохраняются на диск. Это приводит к существенной деградации времени YTsaurus-джобов, выполняющих `JOIN`. Для решения этой проблемы можно увеличить значение прагмы [yt.CommonJoinCoreLimit](https://ytsaurus.tech/docs/ru/yql/syntax/pragma/yt.md#ytcommonjoincorelimit), либо поменять местами стороны `JOIN`.
* `yt/total/data/input/data_weight` (Sum) &mdash; суммарный объём данных, обработанный всеми джобами всех YTsaurus-операций запроса. При отсутствии изменений в плане запроса, изменение этой статистики говорит об изменении входного объёма данных запроса.

### Поиск самой медленной YTsaurus-операции запроса

На вкладке `Progress` YQL-запроса нужно переключиться в режим `Timeline`:
![](../../../images/timeline.png)

В этом режиме наглядно видно, какая YTsaurus-операция больше всего повлияла на время исполнения YQL-запроса. Можно также раскрыть детали исполнения разных стадий операции:
![](../../../images/pending.png)

Здесь видно, что операция долго стояла в статусе `Pending`, т. е. ей не хватало лимитов на число работающих операций в пуле.

Для дальнейшего анализа можно открыть медленную операцию в YTsaurus интерфейсе, кликнув на её название в левой колонке timeline. В YTsaurus-операции в первую очередь стоит обратить внимание на `Total job wall time` и `Total CPU time spent`. Если эти значения для двух запусков YQL-запроса существенно не изменились, но при этом изменился `Duration`, то это сигнализирует о проблемах в пуле запроса. Нужно кликнуть на название пула
![](../../../images/pool.png)
и открыть его в интерфейсе YTsaurus на вкладке `Monitoring` для анализа его нагрузки.
