# Оптимизация

Когда мы говорим об "эффективности запроса" мы подразумеваем то, насколько эффективно запрос расходует ресурсы системы. В первую очередь мы обращаем внимание на:

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

В наших интересах, чтобы запросы меньше нагружали сервер и наш компьютер. Тогда мы быстрее получим результат. В главах этого раздела мы разберем как оптимизировать свои запросы.

Но сначала обсудим то, как мы будем разбираться в эффективности запроса:

* [Как проверить эффективность запроса](#kak-proverit-effektivnost-zaprosa)
* [Оператор EXPLAIN](#explain)
* [DDL таблицы](#ddl-tablicy)

## Как проверить эффективность запроса

### system.query\_log

Для  оценки эффективности запроса можно использовать системную таблицу **system.query\_log.**

При подключении к лерими нам она недоступна, но доступна вью к ней — **my.query\_log.** Вот пример запроса, где мы увидим все запросы к таблице **crs\_available\_resource\_to\_procedure:**

```sql
SELECT event_time, query, read_rows, read_bytes, result_rows, result_bytes, memory_usage
FROM my.query_log
WHERE query ilike '%crs_available_resource_to_procedure%'
	and query not ilike '%from my%'
	and type = 2
ORDER BY event_time DESC
```

* **event\_time** — время выполнения запроса
* **query** — текст запроса
* **read\_rows** — общее количество строк, считанных из всех таблиц и табличных функций, участвующих в запросе.
* **read\_bytes** — общее количество байтов, считанных из всех таблиц и табличных функций, участвующих в запросе.
* **result\_rows** — количество строк в результате запроса SELECT или количество строк в запросе INSERT.
* **result\_bytes** — объём RAM в байтах, использованный для хранения результата запроса.
* **memory\_usage** — потребление RAM запросом.

## EXPLAIN

Это оператор, показывающий план выполнения запроса. Благодаря нему можно узнать, как запрос будет выполняться СУБД.

* Может использоваться без параметров. Такой запрос показывает план запроса:

```sql
EXPLAIN SELECT toYYYYMM(signed_dt), count() as cnt
FROM data_analyzer.diagnosis_dst_meta
GROUP BY toYYYYMM(signed_dt)
HAVING toYYYYMM(signed_dt) IN (202501, 202502, 202503)
```

<figure><img src="https://2436045964-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FCZ9JZpjgSMxqwUmrf0Bd%2Fuploads%2FJ4WWBDBACml0nJqDxtjy%2Fimage.png?alt=media&#x26;token=2c66e9dc-a0ff-44d1-a9f2-f332e1a3c034" alt=""><figcaption></figcaption></figure>

* Может использоваться с SYNTAX — отображает запрос после выполнения оптимизации кликхаусом:

```sql
EXPLAIN SYNTAX SELECT toYYYYMM(signed_dt), count() as cnt
FROM data_analyzer.diagnosis_dst_meta
GROUP BY toYYYYMM(signed_dt)
HAVING toYYYYMM(signed_dt) IN (202501, 202502, 202503)
```

<figure><img src="https://2436045964-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FCZ9JZpjgSMxqwUmrf0Bd%2Fuploads%2FScHxDWVGJsTw8dxOj4aP%2Fimage.png?alt=media&#x26;token=568e29d9-de87-4c8e-aac1-7223805253b1" alt=""><figcaption></figcaption></figure>

* Можно вывести подробный план запроса в JSON. Попробуйте и изучите результат:

```sql
EXPLAIN PLAN json = 1, indexes = 1, description = 1
SELECT toYYYYMM(signed_dt), count() as cnt
FROM data_analyzer.diagnosis_dst_meta
GROUP BY toYYYYMM(signed_dt)
HAVING toYYYYMM(signed_dt) IN (202501, 202502, 202503)
```

## DDL таблицы

Для эффективной работы с таблицами часто нам нужно ознакомиться с DDL этих таблиц.

**DDL (Data Definition Language)** — запрос, который эту таблицу создаёт. Нам полезно знать типы данных, ключ партиционирования, ключи сортировки, гранулярность индекса, настройки.

Мы можем узнать DDL через интерфейс:

<figure><img src="https://2436045964-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FCZ9JZpjgSMxqwUmrf0Bd%2Fuploads%2FFPFayFMSYewZxz7T01aO%2Fimage.png?alt=media&#x26;token=9f366fad-1f01-410f-accd-207ad36847e3" alt=""><figcaption><p>DDL таблицы в DBeaver</p></figcaption></figure>

Или при помощи запроса:

```sql
SHOW CREATE data_analyzer.diagnosis_dst_meta
```

Обратим внимание на последние строки:

```sql
PARTITION BY toYYYYMM(signed_dt) -- ключ партиционирования
PRIMARY KEY (document_class_id, -- индекс
 document_id)
ORDER BY (document_class_id, -- ключи сортировки
 document_id,
 xpath,
 line_id)
SETTINGS index_granularity = 8192; -- настройки гранулярности индекса
```

## Продолжение

Теперь когда мы разобрались с основными понятиями можно переходить непосредственно к способам оптимизации. В этом разделе главы разделены по темам — либо в зависимости от оператора, который обсуждается в главе; либо по смыслу. Вы можете возвращаться к этой странице, чтобы повторить определения.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://um-dzm.gitbook.io/ch_optimize/optimizaciya.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
