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

<!-- source: ru/faq/_includes/yql.md -->
# YQL

## Общие вопросы {#common}

### Как выбрать из таблицы строчки по заданному списку ключей? {#explicit-keys}

Выборка строчек таблицы по заданному списку значений первичного ключа (или префикса ключа) таблицы выполняется с помощью оператора `IN`:

```yql
DECLARE $keys AS List<UInt64>;

SELECT * FROM some_table
WHERE Key1 IN $keys;
```

В случае если выборка делается по составному ключу, параметр запроса должен иметь тип списка таплов:

```yql
DECLARE $keys AS List<Tuple<UInt64, String>>;

SELECT * FROM some_table
WHERE (Key1, Key2) IN $keys;
```

Для эффективного выполнения выборки важно, чтобы типы значений в параметрах совпадали с типами ключевых колонок в таблице.

### Осуществляется ли поиск по индексу для условий, содержащих оператор LIKE? {#like-index}

Оператор `LIKE` может быть использован для поиска по индексу таблицы только в случае, если он задает префикс строки:

```yql
SELECT * FROM string_key_table
WHERE Key LIKE "some_prefix%";
```

### Почему в результате запроса выводится только 1000 строк? {#result-rows-limit}

1000 строк — ограничение на размер одного результата для YQL запроса. В случае если результат запроса был обрезан, он будет помечен флагом `Truncated`. Чтобы получить большее количество строк из таблицы, можно воспользоваться [постраничным выводом](https://ydb.tech/docs/ru/dev/paging.md) или операцией `ReadTable`.

### Как экранировать кавычки JSON-строк при добавлении их в таблицу? {#escaping-quotes}

Рассмотрим пример c двумя возможными вариантами добавления JSON-строки в таблицу:

```yql
UPSERT INTO test_json(id, json_string)
VALUES
    (1, Json(@@[{"name":"Peter \"strong cat\" Kourbatov"}]@@)),
    (2, Json('[{"name":"Peter \\\"strong cat\\\" Kourbatov"}]'))
;
```

Для вставки значения в первой строке используется `raw string` и способ экранирования с помощью `\"`. Для вставки второй строки используется экранирование через `\\\"`.

Мы рекомендуем применять `raw string` и способ экранирования с помощью `\"`, так как он более нагляден.

### Как обновить только те значения, ключей которых нет в таблице? {#update-non-existent}

Можно использовать операцию `LEFT JOIN`, чтобы пометить отсутствующие в таблице ключи, после чего обновить их значения:

```yql
DECLARE $values AS List<Struct<Key: UInt64, Value: String>>;

UPSERT INTO kv_table
SELECT v.Key AS Key, v.Value AS Value
FROM AS_TABLE($values) AS v
LEFT JOIN kv_table AS t
ON v.Key = t.Key
WHERE t.Key IS NULL;
```

## Операции Join {#joins}

### Есть ли особенности в работе операции Join? {#join-operations}

Операция `Join` в YDB выполняется одним из двух способов:

* Common Join;
* Index Lookup Join.

### Common Join {#common-join}

Содержимое обеих таблиц (левая и правая части `Join`) отправляется на выполняющий запрос узел, где операция выполняется над данными целиком. Это универсальный способ выполнения операции `Join`, который применяется в случае, когда более оптимальные способы неприменимы. Для больших таблиц такой способ или работает медленно, или в общем случае не работает из-за превышения лимитов на пересылку данных.

### Index lookup Join {#index-lookup-join}

Для строчек из левой части операции `Join` осуществляется поиск (lookup) соответствующих значений в правой части. Данный способ применяется, когда правая часть является таблицей и ключ операции `Join` является префиксом ее первичного ключа или ключа вторичного индекса. При использовании данного способа из правой таблицы делаются ограниченные выборки, вместо полного чтения, что позволяет использовать его при работе с большими таблицами.

{% note info %}

Для большинства OLTP запросов рекомендуется использовать Index Lookup Join с небольшим размером левой части. Такие операции читают мало данных и могут быть выполнены эффективно.

{% endnote %}

### Как сделать Join с данными из параметров запроса? {#constant-table-join}

Данные из параметров запроса можно использовать как константную таблицу. Для этого нужно использовать модификатор `AS_TABLE` с параметром, имеющим тип списка структур:

```yql
DECLARE $data AS List<Struct<Key1: UInt64, Key2: String>>;

SELECT * FROM AS_TABLE($data) AS d
INNER JOIN some_table AS t
ON t.Key1 = d.Key1 AND t.Key2 = d.Key2;
```

Явного ограничения на количество записей в константной таблице нет, но нужно иметь в виду стандартное ограничение на общий размер параметров запроса (50 МБ).

### Как лучше реализовать запрос вида (key1, key2) IN ((v1, v2), (v3, v4), ...)? {#key-pairs-in}

Это лучше записывать через JOIN с константной таблицей:

```yql
$keys = AsList(
    AsStruct(1 AS Key1, "One" AS Key2),
    AsStruct(2 AS Key1, "Three" AS Key2),
    AsStruct(4 AS Key1, "One" AS Key2)
);

SELECT t.* FROM AS_TABLE($keys) AS k
INNER JOIN table1 AS t
ON t.Key1 = k.Key1 AND t.Key2 = k.Key2;
```

## Транзакции {#transactions}

### Насколько эффективно выполнение нескольких запросов в транзакции? {#transaction-queries}

При последовательном выполнении нескольких запросов, суммарный latency для транзакции может быть больше, чем при выполнении тех же операций в рамках одного запроса. В первую очередь это обусловлено дополнительными сетевыми задержками на выполнение каждого из запросов. Поэтому в случае, когда для транзакции не требуется интерактивность, рекомендуется формулировать все операции в одном YQL запросе.

### Является ли отдельный запрос атомарным? {#atomic-query}

В общем случае YQL-запросы могут выполняться в несколько последовательных фаз. Например, запрос с операцией Join может быть выполнен в две фазы, читающие данные левой и правой таблицы соответственно. Этот аспект является важным при выполнении запроса в транзакции с низким уровнем изоляции (`online_read_only`), так как в этом случае данные между фазами выполнения могут быть изменены другими транзакциями.
<!-- endsource: ru/faq/_includes/yql.md -->
