# Неблокирующие запросы

## Ситуации возможных блокировок {: #blocking_factors }

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

- SQL-запрос может вызывать значительные задержки и блокировать
  транзакционный поток, что будет мешать выполнению других запросов
- SQL-запрос не должен приводить к исчерпанию памяти на отдельных узлах
  кластера
- при объединении результатов локальных запросов в виртуальную таблицу
  на узле-маршрутизаторе нужно следить, чтобы эта таблица не
  разрасталась бесконтрольно

## Параметры для ограничения запросов {: #query_limitations }

Для решения этих задач в DQL- и DML-запросах предусмотрены следующие
необязательные параметры:

- `SQL_VDBE_OPCODE_MAX`, ограничение на максимальное количество команд
 при исполнении локального плана виртуальным движком базы данных
  ([VDBE](https://www.sqlite.org/vdbe.html)) на экземпляре кластера.
- `SQL_MOTION_ROW_MAX`, ограничение на максимальное число строк в
  промежуточной виртуальной таблице, собирающей результаты отдельных
  локальных запросов.

Параметр `SQL_VDBE_OPCODE_MAX` ограничивает счетчик команд при исполнении
скомпилированного запроса из
[опкодов](../../overview/glossary.md#opcode) в VDBE-машине (число команд
прямо пропорционально числу опкодов). Ограничение влияет на количество
обработанных кортежей локальным SQL на узлах кластера в DQL-запросах и
позволяет предотвратить выполнение SQL-команды в тех случаях, если
запрашиваемая таблица слишком велика. Это может сигнализировать
пользователю о необходимости переделать запрос (например, отказаться от
полного сканирования (`SELECT * ...`) такой таблицы в пользу выборке
данных по индексу).

<!--
Скомпилированный план локального SQL-запроса, состоящего из опкодов, 
можно посмотреть так:

```
box.execute([[EXPLAIN SELECT * FROM warehouse]])
---
- metadata:
  - name: addr
    type: integer
  - name: opcode
    type: text
  - name: p1
    type: integer
  - name: p2
    type: integer
  - name: p3
    type: integer
  - name: p4
    type: text
  - name: p5
    type: text
  - name: comment
    type: text
  rows:
  - [0, 'Init', 0, 1, 0, '', '00', null]
  - [1, 'OpenSpace', 1, 1025, 0, '', '00', null]
  - [2, 'IteratorOpen', 1, 0, 1, '', '00', null]
  - [3, 'Rewind', 1, 10, 2, '0', '00', null]
  - [4, 'Column', 1, 0, 2, '', '00', null]
  - [5, 'Column', 1, 1, 3, '', '00', null]
  - [6, 'Column', 1, 2, 4, '', '00', null]
  - [7, 'Column', 1, 3, 5, '', '00', null]
  - [8, 'ResultRow', 2, 4, 0, '', '00', null]
  - [9, 'Next', 1, 4, 0, '', '01', null]
  - [10, 'Halt', 0, 0, 0, '', '00', null]
...
```

В разделе `rows` перечислены опкоды запроса.
Читающие опкоды здесь — номера 4, 5, 6, 7, 8, 9.
Каждое прохождение исполнения запроса через опкод
увеличивает счетчик команд на 1. В зависимости от
количества кортежей в таблице, для читающего опкода
может понадобиться несколько прохождений. Соответственно,
счетчик `SQL_VDBE_OPCODE_MAX` будет практически всегда
выше числа опкодов. Так, в приведенном примере 11 опкодов,
но минимальное значение `SQL_VDBE_OPCODE_MAX` — 15.

 -->

См. также:

  - [The SQLite Bytecode Engine](https://www.sqlite.org/opcode.html)

## Примеры {: #examples }

??? example "Тестовые таблицы"
    Примеры использования команд включают в себя запросы к [тестовым
    таблицам](../legend.md).

Пример совместного использования `SQL_VDBE_OPCODE_MAX` и `SQL_MOTION_ROW_MAX`:


```sql
SELECT * FROM warehouse OPTION(SQL_VDBE_OPCODE_MAX = 30, SQL_MOTION_ROW_MAX = 5);
+----+----------+---------+
| ID | ITEM     | TYPE    |
+=========================+
| 1  | "bricks" | "heavy" |
|----+----------+---------|
| 2  | "bars"   | "light" |
|----+----------+---------|
| 3  | "blocks" | "heavy" |
|----+----------+---------|
| 4  | "piles"  | "light" |
|----+----------+---------|
| 5  | "panels" | "light" |
+----+----------+---------+
(5 rows)
```

Если ограничения не позволяют выполнить запрос, то будет возвращена
ошибка.

При меньших значениях `SQL_VDBE_OPCODE_MAX`:

```
---
- null
- ("Reached a limit on max executed vdbe opcodes. Limit: XX\")
...
```

При слишком низком значении `SQL_MOTION_ROW_MAX`:

```
---
- null
- (Exceeded maximum number of rows (4) in virtual table: Х\")
...
```
