summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorulya-sidorina <[email protected]>2023-06-23 16:09:03 +0300
committerulya-sidorina <[email protected]>2023-06-23 16:09:03 +0300
commit5e46f0301456285f1a47076638fcd7679cccafa4 (patch)
treefcc464ca983796e42859cfb23656fdd2de738251
parentcc52bb3da65301318cbaf8fbb6609ef6d5e3cf68 (diff)
update query plan documentation
docs(ydb): fix query plan description
-rw-r--r--ydb/docs/ru/core/_assets/explain_ui.pngbin0 -> 42035 bytes
-rw-r--r--ydb/docs/ru/core/_assets/query_plan_ui.pngbin0 -> 181146 bytes
-rw-r--r--ydb/docs/ru/core/operations/query_plan.md143
-rw-r--r--ydb/docs/ru/core/operations/toc_i.yaml3
4 files changed, 145 insertions, 1 deletions
diff --git a/ydb/docs/ru/core/_assets/explain_ui.png b/ydb/docs/ru/core/_assets/explain_ui.png
new file mode 100644
index 00000000000..7ab9a4f699e
--- /dev/null
+++ b/ydb/docs/ru/core/_assets/explain_ui.png
Binary files differ
diff --git a/ydb/docs/ru/core/_assets/query_plan_ui.png b/ydb/docs/ru/core/_assets/query_plan_ui.png
new file mode 100644
index 00000000000..bfb0a562d5b
--- /dev/null
+++ b/ydb/docs/ru/core/_assets/query_plan_ui.png
Binary files differ
diff --git a/ydb/docs/ru/core/operations/query_plan.md b/ydb/docs/ru/core/operations/query_plan.md
new file mode 100644
index 00000000000..3a14dd7a129
--- /dev/null
+++ b/ydb/docs/ru/core/operations/query_plan.md
@@ -0,0 +1,143 @@
+# Построение планов запросов
+
+Чтобы лучше понимать работу запросов, вы можете получить и проанализировать план запроса.
+Структура плана запроса в {{ ydb-short-name }} представляет собой граф. Каждый узел содержит информацию об операциях и таблицах.
+
+Тип операции | Аттрибуты | Комментарий
+--- | --- | ---
+`TableFullScan` | `ReadColumns` - читаемые колонки | полное сканирование таблицы
+`TableRangeScan` | `ReadColumns` - читаемые колонки<br>`ReadRange` - диапазон ключей, по которому выполняется чтение | чтение определенного диапазона записей
+`TablePointLookup` | `ReadColumns` - читаемые колонки<br>`ReadRange` - диапазон или точка, по которым выполняется чтение | чтение по ключу или префиксу ключа
+`Upsert` | `Columns` - колонки, которые содержит добавляемая строка | добавление строк в таблицу
+`Delete` | | удаление строк из таблицы
+`Join` | в описании операции указана используемая стратегия join'а: <br>`Inner`<br>`Left`<br>`LeftOnly`<br>`Right`<br>`RightOnly`<br>`LeftSemi`<br>`RightSemi`<br>`Full`<br>`Cross` | объединение двух таблиц на основе выбранной стратегии
+`Filter` | `Predicate` - условие фильтрации<br>`Limit` - лимит на число строк | фильтрация строк
+`Aggregate` | `GroupBy` - колонки, по которым выполняется агрегирование<br>`Aggregation`- условие агрегирования | агрегирование строк
+`Sort` | `SortBy` - колонки, по которым выполняется сортировка | сортировка результата
+`TopSort` | `TopSortBy` - колонки, по которым выполняется сортировка<br>`Limit` - лимит на число строк | сортировка результата с применением лимита
+`Limit` | | величина лимита на число строк
+`Offset` | | величина смещения
+`Union` | | объединение результатов двух запросов в один результирующий набор
+
+{% list tabs %}
+
+- {{ ydb-short-name }} CLI
+
+ Получить план запроса через {{ ydb-short-name }} CLI можно с помощью команды `explain`:
+ ```
+ ydb -e grpcs://<эндпоинт> -d <база данных> table query explain \
+ -q "SELECT season_id, episode_id, title
+ FROM episodes
+ WHERE series_id = 1
+ AND season_id > 1
+ ORDER BY season_id, episode_id
+ LIMIT 3"
+ ```
+
+ Полученный результат:
+ ```
+ Query Plan:
+ ResultSet
+ └──Limit (Limit: 3)
+ └──<Merge>
+ └──TopSort (Limit: 3, TopSortBy: )
+ └──Filter (Predicate: Exist(item.season_id) And Exist(item.series_id))
+ └──TablePointLookup (ReadRange: [series_id (1), season_id (1, +∞), episode_id (-∞, +∞)], ReadColumns: [episode_id, season_id, title, series_id], Table: episodes)
+ Tables: [episodes]
+ ```
+
+ Дополнительно к плану запроса вы можете получить AST (абстрактное синтаксическое дерево).
+ Раздел AST содержит представление на внутреннем языке miniKQL.
+
+ Для получения AST необходимо вызвать `explain` с флагом `--ast`:
+ ```
+ ydb -e grpcs://<эндпоинт> -d <база данных> table query explain \
+ -q "SELECT season_id, episode_id, title
+ FROM episodes
+ WHERE series_id = 1
+ AND season_id > 1
+ ORDER BY season_id, episode_id
+ LIMIT 3" --ast
+ ```
+
+ Полученный AST:
+ ```
+ Query AST:
+ (
+ (let $1 (KqpTable '"episodes" '"72075186224045943:83859" '"" '1))
+ (let $2 '('"episode_id" '"season_id" '"title" '"series_id"))
+ (let $3 (Uint64 '1))
+ (let $4 (KqpRowsSourceSettings $1 $2 '() '((KqlKeyExc $3 $3) (KqlKeyInc $3))))
+ (let $5 (Uint64 '"3"))
+ (let $6 (DqPhyStage '((DqSource (DataSource '"KqpReadRangesSource") $4)) (lambda '($12) (block '(
+ (let $13 (Bool 'true))
+ (return (FromFlow (TopSort (OrderedMap (OrderedFilter (ToFlow $12) (lambda '($14) (And (Exists (Member $14 '"season_id")) (Exists (Member $14 '"series_id"))))) (lambda '($15) (AsStruct '('"episode_id" (Member $15 '"episode_id")) '('"season_id" (Member $15 '"season_id")) '('"title" (Member $15 '"title"))))) $5 '($13 $13) (lambda '($16) '((Member $16 '"season_id") (Member $16 '"episode_id"))))))
+ ))) '('('"_logical_id" '842) '('"_id" '"14388682-e03b28dd-60f91f84-d7cd002f"))))
+ (let $7 (DqCnMerge (TDqOutput $6 '0) '('('"season_id" '"Asc") '('"episode_id" '"Asc"))))
+ (let $8 (DqPhyStage '($7) (lambda '($17) (FromFlow (Take (ToFlow $17) $5))) '('('"_logical_id" '855) '('"_id" '"295c0459-34d4b026-b467e71f-35402430"))))
+ (let $9 '('"season_id" '"episode_id" '"title"))
+ (let $10 (DqCnResult (TDqOutput $8 '0) $9))
+ (let $11 (OptionalType (DataType 'Uint64)))
+ (return (KqpPhysicalQuery '((KqpPhysicalTx '($6 $8) '($10) '() '('('"type" '"data")))) '((KqpTxResultBinding (ListType (StructType '('"episode_id" $11) '('"season_id" $11) '('"title" (OptionalType (DataType 'String))))) '0 '0)) '('('"type" '"data_query"))))
+ )
+ ```
+
+- Embedded UI
+
+ План запроса также можно получить через [Embedded UI](../maintenance/embedded_monitoring/ydb_monitoring.md). Для этого необходимо перейти на страницу бд в раздел `Query` и нажать `Explain`:
+
+ ![explain_ui](../_assets/explain_ui.png)
+
+ Полученный результат:
+
+ ![query_plan_ui](../_assets/query_plan_ui.png)
+
+{% endlist %}
+
+# Использование планов при оптимизации запросов
+
+Рассмотрим запрос, выполняющий поиск серии по названию
+
+``` sql
+SELECT season_id, episode_id
+ FROM episodes
+ WHERE title = 'The Work Outing'
+```
+```
+Query Plan:
+ResultSet
+└──Limit (Limit: 1001)
+ └──<UnionAll>
+ └──Limit (Limit: 1001)
+ └──Filter (Predicate: item.title == "The Work Outing")
+ └──TableFullScan (ReadRanges: ["series_id (-∞, +∞)","season_id (-∞, +∞)","episode_id (-∞, +∞)"], ReadColumns: ["episode_id","season_id","title"], Table: episodes)
+ Tables: ["episodes"]
+```
+
+По плану видно, что выполнение запроса приводит к полному сканированию таблицы.
+Попробуем оптимизировать запрос посредством добавления вторичного индекса для колонки `title`.
+
+``` sql
+ALTER TABLE episodes
+ ADD INDEX title_index GLOBAL ON (title)
+```
+
+Построим план того же запроса с использованием вторичного индекса `title_index`, обратите вминание, что вторичный индекс надо явно указать в запросе через конструкцию `VIEW` (подробнее про вторичные индексы можно прочитать [здесь](../best_practices/_includes/secondary_indexes.md)).
+
+``` sql
+SELECT season_id, episode_id
+ FROM episodes VIEW title_index
+ WHERE title = 'The Work Outing'
+```
+```
+Query Plan:
+ResultSet
+└──Limit (Limit: 1001)
+ └──<UnionAll>
+ └──Limit (Limit: 1001)
+ └──Filter (Predicate: Exist(item.title))
+ └──TablePointLookup (ReadRange: ["title (The Work Outing)","series_id (-∞, +∞)","season_id (-∞, +∞)","episode_id (-∞, +∞)"], ReadLimit: 1001, ReadColumns: ["episode_id","season_id","title"], Table: episodes/title_index/indexImplTable)
+ Tables: ["episodes/title_index/indexImplTable"]
+```
+
+С использованием вторичного индекса запрос выполняется оптимально через чтение индексной таблицы по ключу. \ No newline at end of file
diff --git a/ydb/docs/ru/core/operations/toc_i.yaml b/ydb/docs/ru/core/operations/toc_i.yaml
index 4c44d6ac742..f8ad7daf3d8 100644
--- a/ydb/docs/ru/core/operations/toc_i.yaml
+++ b/ydb/docs/ru/core/operations/toc_i.yaml
@@ -4,4 +4,5 @@ items:
hidden: true
- name: Пользовательские атрибуты таблицы
href: manage-users-attr.md
- \ No newline at end of file
+- name: Построение планов запросов
+ href: query_plan.md \ No newline at end of file