YQL

Общие вопросы

Операции Join

Есть ли особенности в работе операции Join?

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

  • Common Join
  • Index Lookup Join

Common Join

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

Index lookup Join

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

Примечание

Рекомендуется всегда использовать Index Lookup Join.

Что делать, если при запросе я получаю ошибку "Datashard: Reply size limit exceeded"?

При некорректном составлении запроса может быть превышен допустимый лимит объёма данных, которые можно прочитать с определенного шарда. В результате запроса, возвращается более 50 Мбайт с одного шарда.

Рекомендации:

  • Общая рекомендация — уменьшить обхъем данных, обрабатываемых в транзакции;
  • Если выполняется операция Join, необходимо убедиться, что операция выполняется Index lookup JOIN;
  • Если осуществляется простая выборка, нужно убедиться, что она делается по ключам, или добавить LIMIT в запрос.

Как обрабатывает оператор IN?

Выборка IN на данный момент эффективно работает только для явно заданных константных значений ключа.

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

Чтобы сделать запрос к таблице со сложным первичным ключом, используйте операцию Join с константной таблицей, содержащей поля первичного ключа. При выполнении операции Join константная таблица должна быть слева. Важно, чтобы тип ключей в константной таблице точно совпадал с типами ключей в таблице для выборки.

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

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

Есть ли ограничения на количество записей в константной таблице?

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

Транзакции

Почему в результате запроса выводится только 1000 строк?

1000 строк — ограничение на размер ответа. Если ответ был ограничен он будет помечен флагом Truncated. Чтобы вывести большее количество строк, воспользуйтесть постраничным выводом. Чтобы прочитать таблицу целиком, воспользуйтесь функцией readTable().

Является ли отдельный запрос атомарным?

В общем случае YQL-запросы и выражения не являются атомарными. Например, для операции UPDATE последовательно выполняются действия Read и Write, и при низких уровнях изоляции между ними данные могут быть изменены другими транзакциями. Однако все уровни изоляции кроме Serializable являются ReadOnly, так что UPDATE всегда выполняется в сериализуемой транзакции.

Что оптимальнее, несколько операций в одной транзакции, или одна операция на транзакцию?

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

Как сделать вставку только тех значений, ключей которых нет в таблице?

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

$Key = 155;
$Value = 1700;

$pair = (SELECT $Key AS Id, $Value AS Value);

$data = (
    SELECT p.Id AS Id, t.Value AS Value, p.Value AS NewValue
    FROM $pair AS p
    LEFT JOIN [test_table] AS t
    ON p.Id == t.Id
);

SELECT Id, Value, NewValue, IF (Value IS NULL, true, false) AS Inserted FROM $data;

UPSERT INTO [test_table]
SELECT Id, NewValue AS Value FROM $data
WHERE Value IS NULL;

Эту же операцию можно осуществить с помощью двух запросов:

  1. Прочитать значения по ключу;
  2. Если значение есть — выполнить COMMIT, если значения нет — выполнить UPSERT + COMMIT.

Осуществляется ли поиск по индексу для условий, содержащих операторы AND и LIKE?

Расмотрим запрос SELECT * FROM t WHERE t.shard_key = ‘my_shard_key’ AND t.key LIKE ‘some_prefix%’. Для первой части условия t.shard_key = ‘my_shard_key’ сработает поиск по индексу. Затем, к полученной выборке применится операция scan с учетом фильтром.