Выполнение запросов
Эта статья описывает процесс выполнения запросов в YDB. Она предназначена для ознакомления пользователей с возможностями и ограничениями движка выполнения запросов YDB, включая ключевые особенности, такие как поддерживаемый язык запросов и общий порядок их выполнения. Также здесь вводится базовая терминология и концепции, которые используются в других разделах документации.
YDB предоставляет единый интерфейс для выполнения запросов, способный эффективно обрабатывать широкий спектр нагрузок — от высоконагруженных транзакционных OLTP-запросов до сложных аналитических OLAP-запросов. Такой подход позволяет приложениям выполнять транзакционные и аналитические запросы прозрачно, без необходимости использовать разные API для разных типов нагрузки.
Для выполнения запросов используется распределённый движок, спроектированный с учётом масштабируемости и эффективности в больших распределённых средах. При запуске запроса YDB автоматически распределяет работу между несколькими узлами, максимально учитывая локальность данных — обрабатывает данные там, где они хранятся. Это снижает избыточные сетевые пересылки. Кроме того, применяется вычислительный pushdown (вынос фильтрации и вычислений ближе к слою хранения), что дополнительно ускоряет обработку. Благодаря этим техникам YDB эффективно справляется со сложными запросами и большими нагрузками на уровне кластера.
Общий порядок работы
Далее описан пошаговый процесс обработки SQL-запросов в YDB. Знание этого процесса помогает лучше понять архитектуру и внутреннее устройство YDB.

-
Подключение к базе данных
Приложение использует один из официальных SDK YDB для подключения к базе данных. SDK автоматически управляет пулом сессий — логических подключений, необходимых для выполнения запросов. Каждая сессия физически связана с одним из узлов кластера. Когда требуется выполнить запрос, SDK предоставляет готовую сессию из пула, избавляя разработчика от необходимости ручного управления соединениями. -
Начало транзакции и отправка запроса
Используя активную сессию, приложение может начать транзакцию и сформировать запрос на языке YQL согласно своей бизнес-логике, после чего отправить его в кластер YDB. -
Парсинг и поиск в кеше планов
На серверной стороне узел YDB, получивший запрос, сначала проверяет его корректность (парсинг и анализ). Затем система проверяет наличие готового физического плана выполнения в кеше запросов. Если план найден, он используется повторно. -
Оптимизация и подготовка плана
Если подходящего плана нет, оптимизатор запросов формирует новый физический план, определяющий наиболее эффективный способ выполнения запроса в распределённой системе. Подробнее о принципах оптимизации запросов и видах планов см. в статье Оптимизация запросов в YDB. -
Распределённое выполнение запроса
Согласно подготовленному физическому плану YDB начинает распределённое выполнение запроса: обработка делится между несколькими узлами, каждый из которых отвечает за свою часть расчетов или обращения к данным согласно полученному плану. Такой параллелизм обеспечивает высокую скорость и масштабируемость выполнения даже для объёмных выборок. -
Потоковая передача результатов клиенту
Если запрос возвращает результат (SELECTи т. п.), он поступает в приложение в виде одного или нескольких результирующих наборов, которые представляют собой строго типизированные таблицы. Данные передаются потоково (частями), это позволяет обрабатывать результаты сразу по мере поступления и эффективно работать с большими выборками, не загружая всю выборку в память. -
Продолжение или завершение транзакции
После получения результатов приложение может либо продолжить транзакцию, отправив дополнительные запросы в её контексте, либо завершить её фиксацией изменений (commit).
Более подробное описание перечисленных этапов и связанных с ними понятий приведено в отдельных разделах ниже.
Сессии
Сессия в YDB — это логическое "соединение" с базой данных, которое хранит контекст, необходимый для выполнения запросов и управления транзакциями. Внутри сессии поддерживается состояние транзакций и другая рабочая информация, что позволяет выполнять связанные друг с другом запросы как часть одной транзакции. Большинство операций с запросами выполняется в контексте активной сессии.
Сессии являются долгоживущими объектами. Одна из их важных задач — эффективное распределение нагрузки: за счёт распределения сессий и связанных с ними запросов по разным узлам кластера YDB достигает высокой доступности и масштабируемости.
На практике создавать, переиспользовать и удалять сессии вручную не требуется. Все официальные SDK для YDB предоставляют встроенный пул сессий: SDK сам управляет жизненным циклом сессий, создаёт их по мере необходимости, повторно использует и возвращает обратно в пул — всё это прозрачно для пользователя и не требует дополнительной логики в приложении.
Транзакции
Каждый запрос в YDB выполняется в контексте транзакции, что обеспечивает согласованность и надёжное хранение данных. Транзакциями можно управлять явно (через отдельные вызовы в SDK) или указывать соответствующие флаги во время выполнения запроса.
YDB также поддерживает интерактивные транзакции, которые дают возможность выполнять несколько запросов в рамках одной транзакции, позволяя при этом вашему приложению выполнять пользовательскую логику между этими запросами. Это позволяет строить сложные рабочие процессы, в которых требуется рассматривать несколько связанных операций как единую атомарную единицу.
Для получения подробной информации о транзакциях и доступных режимах транзакций в YDB смотрите статью Транзакции.
Повторные выполнения (Retries)
В YDB применяется механизм оптимистичных блокировок для управления транзакциями. Это означает, что транзакция может быть прервана во время выполнения, если выявлен конфликт и система не может гарантировать нужный уровень изоляции — например, если две транзакции одновременно изменяют одни и те же данные. Помимо конфликтов, в распределённой среде возможны временная недоступность отдельных узлов из-за сетевых сбоев, отказов оборудования или технических работ, что также может привести к необходимости повторного выполнения транзакции.
Повторное выполнение всегда следует реализовывать на уровне всей транзакции, а не отдельного запроса. В интерактивных транзакциях последовательность выполнения и промежуточные результаты отдельных запросов могут влиять на последующие действия. Поэтому, если запрос завершился ошибкой из-за конфликта или временной ошибки, необходимо повторять всю транзакцию с самого начала, чтобы обеспечить корректность и консистентность данных.
Все официальные SDK для YDB предоставляют встроенные механизмы управления транзакциями и повторным выполнением, упрощающие написание приложений. Используя стандартные механизмы повторного выполнения транзакций из SDK, вы автоматически получаете корректную реализацию логики повторного выполнения без необходимости реализовывать её вручную. Подробнее о механизмах повторного выполнения для различных SDK см. Обработка ошибок.
Язык запросов
Запросы для YDB пишутся на YQL — SQL-диалекте, специально адаптированным для распределённых масштабируемых баз данных. Хотя YQL не полностью совместим с ANSI SQL, он во многом сохраняет знакомый синтаксис и принципы SQL, что облегчает обучение и переход для опытных пользователей SQL. Полная справка по языку приведена в документации по YQL.
Большинство операций с данными в YDB осуществляется именно через YQL — он является основным инструментом для работы с данными и администрирования базы. Владение YQL позволяет использовать все возможности распределённой архитектуры YDB и реализовывать сложную бизнес-логику непосредственно в запросах.
YQL поддерживает все основные конструкции SQL, в числе которых:
- Язык манипулирования данными (DML):
SELECT,INSERT,REPLACE,UPDATE,DELETE,UPSERT. - Язык определения данных (DDL):
CREATE,ALTER,DROPдля таблиц, индексов и других объектов схемы. - Соединения — все стандартные виды соединений, а также специальные типы соединений (например,
LEFT SEMI,RIGHT SEMI,ANY). - Агрегации — группировка (
GROUP BY) и оконные функции. - Именованные выражения для структурирования текста запроса.
- Большое количество встроенных функций для обработки разных типов данных и решения сложных задач прямо в запросе.
- Прагмы (pragma) и подсказки (hints) для управления планом выполнения.
Результирующие наборы
Результатом выполнения запроса в YDB может быть один или несколько результирующих наборов (result sets). Результирующий набор похож на таблицу: он содержит строки со строгой типизацией данных в каждом столбце. Строгая типизация результатов обеспечивает предсказуемость и согласованность формата выдачи.
Результирующие наборы могут содержать произвольно большой объём данных, поэтому для их эффективной передачи YDB использует потоковую выдачу (streaming) — результат возвращается на клиент порциями (chunks). Это позволяет сразу начинать обработку данных без ожидания получения всей выборки и минимизирует использование оперативной памяти клиентским приложением.
Ограничения
При работе с запросами в YDB важно учитывать ряд ограничений:
-
Отсутствие схемных транзакций
YDB не поддерживает схемные транзакции, поэтому DDL-операции (создание или изменение таблиц) нельзя объединять с DML-запросами (вставка, изменение или удаление данных) в одной транзакции или одном запросе. -
Большие обновления и оптимистичные блокировки
YDB применяет механизм оптимистичных блокировок. При попытке выполнить очень большиеUPDATEилиDELETEв рамках одной транзакции вероятность конфликтов по блокировкам сильно возрастает, делая такие операции непрактичными для реального использования. -
Ограничения на размер транзакции
Объём данных, записываемых в одной транзакции, ограничен. Подробности см. в разделе Ограничения при выполнении запросов.
Полный список ограничений системы приведён в Ограничения базы данных.