Маршрутизация запросов к данным

Содержание раздела
  1. Определение категории и подкатегории запроса
  2. Стандартный порядок выбора типа датасорса
  3. Примеры запросов по категориям
    1. Реляционные запросы
    2. Запросы агрегации и группировки
    3. Запрос чтения по ключу
    4. Запрос неопределенной категории
  4. Примеры запросов по подкатегориям
    1. Запросы для одного узла
    2. Запросы для набора узлов
    3. Запросы для всех узлов
  5. Маршрутизация запросов к материализованным представлениям

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

Запросы на чтение и выгрузку данных маршрутизируются следующим образом:

  1. Если в запросе указано ключевое слово DATASOURCE_TYPE с датасорсом для исполнения запроса, запрос направляется в указанный датасорс.
  2. Иначе:
    1. Определяются те датасорсы, в которых можно выполнить запрос, — выбираются датасорсы, содержащие данные всех запрашиваемых логических сущностей.
    2. Определяется категория или категория и подкатегория запроса (в зависимости от конфигурации системы; см. ниже).
    3. Выбирается наиболее оптимальный тип датасорса для исполнения запроса (см. ниже).
    4. Запрос направляется в один из датасорсов наиболее оптимального типа. Датасорс выбирается случайным образом среди всех датасорсов, которые относятся к наиболее оптимальному для запроса типу и содержат запрашиваемые сущности.
  3. Если запрос обращается к материализованному представлению, он проходит дополнительные этапы маршрутизации.

Определение категории и подкатегории запроса

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

  • если в конфигурации системы задана секция параметров plugins.category.autoSelect, система использует настройки этой секции и при маршрутизации запроса учитывает как категорию, так и подкатегорию запроса;
  • иначе, если секция plugins.category.autoSelect не задана, система использует настройки секции plugins.category.mapping и учитывает только категорию запроса, без учета его подкатегории.

Категории запросов:

  1. Реляционный запрос (Relational) — запрос с ключевым словом JOIN и (или) подзапросами.
  2. Аналитический запрос (Analytical) — запрос с ключевым словом GROUP BY и агрегатными функциями.
  3. Запрос чтения по ключу (Dictionary) — запрос с условием WHERE на значения первичного ключа.
  4. Другой запрос (Undefined) — запрос, который не соответствует ни одной из предыдущих категорий.

Подкатегории запросов:

  • один узел (ShardOne) — запрос предназначается одному узлу кластера;
  • набор узлов (ShardSet) — запрос предназначается определенным узлам кластера (от 1 до всех);
  • все узлы (ShardAll) — запрос требует исполнения на всех узлах кластера.

Система определяет категорию запроса следующим образом: проверяет запрос на соответствие первой категории, и, если у него есть признаки этой категории, то система относит запрос к первой категории, иначе система проверяет запрос на соответствие второй категории и т.д. Например, запрос с ключевым словом JOIN соответствует первой категории («Реляционный запрос») независимо от наличия признаков других категорий — агрегации, группировки и чтения по ключу. Подкатегория запроса выбирается похожим образом с той разницей, что в этом случае порядок проверки неважен. Примеры запросов по категориям и подкатегориям и см. ниже.

Если при маршрутизации запросов нужно учитывать только категорию запросов, без учета подкатегории, скорректируйте конфигурацию системы: удалите секцию параметров plugins.category.autoSelect и настройте секцию plugins.category.mapping.

Стандартный порядок выбора типа датасорса

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

Например, реляционный запрос, предназначенный для одного узла кластера, будет по возможности исполнен в датасорсе типа ADB. Если в хранилище нет ни одного датасорса типа ADB или в этих датасорсах нет запрашиваемых данных, — запрос будет по возможности исполнен в датасорсе типа ADP, и далее в указанном ниже порядке.

Такой порядок выбора датасорса в зависимости от типа эффективно использует возможности каждой СУБД. При необходимости его можно изменить в конфигурации системы.

Категория запроса Порядок выбора типа датасорса для исполнения запроса
1. Реляционный запрос Один узел: 1. ADB, 2. ADP, 3. ADQM, 4. ADG
Набор узлов: 1. ADB, 2. ADP, 3. ADQM, 4. ADG
Все узлы: 1. ADB, 2. ADP, 3. ADQM, 4. ADG
2. Аналитический запрос Один узел: 1. ADQM, 2. ADB, 3. ADP, 4. ADG
Набор узлов: 1. ADQM, 2. ADB, 3. ADP, 4. ADG
Все узлы: 1. ADQM, 2. ADB, 3. ADP, 4. ADG
3. Запрос чтения по ключу Один узел: 1. ADG, 2. ADB, 3. ADP, 4. ADQM
Набор узлов: 1. ADG, 2. ADB, 3. ADP, 4. ADQM
Все узлы: 1. ADG, 2. ADB, 3. ADP, 4. ADQM
4. Другой запрос Один узел: 1. ADB, 2. ADP, 3. ADQM, 4. ADG
Набор узлов: 1. ADB, 2. ADP, 3. ADQM, 4. ADG
Все узлы: 1. ADB, 2. ADP, 3. ADQM, 4. ADG

Наиболее полный синтаксис запросов доступен в СУБД ADB и ADP. СУБД ADG и ADQM имеют ограничения на выполнение запросов, вызванные особенностями этих СУБД (см. Поддержка SQL).

Примеры запросов по категориям

Реляционные запросы

Реляционный запрос:

SELECT * FROM marketing.sales AS s
JOIN marketing.stores AS st ON s.store_id = st.id

Реляционный запрос, который включает агрегацию, группировку и чтение по ключу (st.id):

SELECT st.id, st.category, SUM(s.product_units) AS product_amount
FROM marketing.stores AS st
JOIN marketing.sales AS s ON st.id = s.store_id
WHERE st.id <> 10004
GROUP BY st.id, st.category
ORDER BY product_amount DESC

Запросы агрегации и группировки

Запрос агрегации и группировки:

SELECT s.product_code, SUM(s.product_units) AS product_amount
FROM marketing.sales AS s
GROUP BY s.product_code
ORDER BY product_amount ASC

Запрос агрегации и группировки, который включает чтение по ключу (s.id):

SELECT s.product_code, SUM(s.product_units) AS product_amount
FROM marketing.sales AS s
WHERE s.id > 20000
GROUP BY s.product_code

Запрос чтения по ключу

SELECT * FROM marketing.sales as s
WHERE s.id BETWEEN 1001 AND 2000

Запрос неопределенной категории

SELECT * FROM marketing.sales AS s
WHERE s.product_units > 2  

Примеры запросов по подкатегориям

Запросы для одного узла

Запрос к логическим таблицам transactions1 (шардирование по col1) и accounts1 (шардирование по colA):

SELECT * FROM transactions1 t
JOIN accounts1 a ON a.colA = t.col1
WHERE t.col1 = 1

Запрос к логической таблице transactions2 (шардирование col1 и col2):

SELECT * FROM transactions2 t
WHERE t.col1 = 1 AND t.col2 = 2 AND amount > 0  

Запросы к логическим таблицам transactions2 (шардирование по col1 и col2) и accounts2 (шардирование по colA и colB):

-- столбцы col1 and colA имеют один тип данных; столбцы col2 and colB также имеют один тип данных

-- запрос объединения таблиц
SELECT * FROM transactions2 t
JOIN accounts a ON a.id = t.account_id
WHERE t.col1 = 1 AND t.col2 = 2 AND a.colA = 1 AND t.colB = 2;

-- запрос с подзапросом
SELECT * FROM transactions2 t
WHERE t.account_id IN (
  SELECT id
  FROM accounts2 a
  WHERE t.col1 = 1 AND t.col2 = 2 AND a.colA = 1 AND a.colB = 2;

Запросы для набора узлов

Запрос к логическим таблицам transactions1 (шардирование по col1) и accounts1 (шардирование по colA):

SELECT * FROM transactions1
WHERE col1 IN (
  SELECT id
  FROM accounts1
  WHERE colA = 1
)

Запрос к логической таблице transactions2 (шардирование по col1 и col2):

SELECT * FROM transactions2 t
WHERE (t.col1 = 1 AND t.col2 = 2) OR ((t.col1 = 1 AND t.col2 = 1) AND amount > 0)

Запросы к логическим таблицам transactions2 (шардирование по col1 и col2) и accounts2 (шардирование по colA и colB):

-- столбцы col1 and colA имеют РАЗНЫЕ типы данных; столбцы col2 and colB имеют один тип данных
SELECT * FROM transactions2 t
JOIN accounts2 a ON a.id = t.account_id
WHERE t.col1 = 1 AND t.col2 = 2 AND a.colA = 1 AND t.colB = 2

Запросы для всех узлов

Запрос к логическим таблицам transactions1 (шардирование по col1) и accounts1 (шардирование по colA):

SELECT * FROM transactions1 t 
JOIN accounts1 a ON a.id = t.account_id
WHERE t.col1 = 1 OR a.colA = 1

Запрос к логической таблице transactions2 (шардирование по col1 и col2):

SELECT * FROM transactions2 t
WHERE (t.col1 = 1 AND t.col2 = 2) OR amount > 0 

Запросы к логическим таблицам transactions2 (шардирование по col1 и col2) и accounts2 (шардирование по colA и colB):

-- столбцы col1 and colA имеют один тип данных; столбцы col2 and colB также имеют один тип данных
SELECT * FROM transactions2 t
JOIN accounts2 a ON a.id = t.account_id
WHERE (t.col1 = 1 AND t.col2 = 2) OR (a.colA = 1 AND t.colB = 2)

Маршрутизация запросов к материализованным представлениям

Запросы к данным материализованных представлений проходят все этапы маршрутизации, описанные выше, и затем — дополнительные этапы:

  1. Если для материализованного представления не указано ключевое слово FOR SYSTEM_TIME, запрос направляется в датасорс, где размещены данные этого представления. Из представления выбираются данные последней версии на момент последней синхронизации представления.
  2. Иначе, если ключевое слово FOR SYSTEM_TIME указано, система проверяет, есть ли в представлении данные за запрашиваемый момент времени:
    • Если в запросе есть ключевое слово DATASOURCE_TYPE, а данных за запрашиваемый момент времени в представлении нет, в ответе возвращается исключение.
    • Если в запросе нет ключевого слова DATASOURCE_TYPE:
      • Если данные есть в представлении, запрос направляется в датасорс, где размещены данные этого представления.
      • Иначе запрос направляется к исходным таблицам датасорса-источника, на которых построено представление.

В запросах к материализованным представлениям доступны не все выражения с ключевым словом FOR SYSTEM_TIME. Подробнее см. в разделе SELECT > Доступность значений FOR SYSTEM_TIME.