Выполнение запросов
Эта статья описывает процесс выполнения запросов в 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в рамках одной транзакции вероятность конфликтов по блокировкам сильно возрастает, делая такие операции непрактичными для реального использования. Для больших изменений рекомендуется использоватьBATCH UPDATE/BATCH DELETE. -
Ограничения на размер транзакции
Объём данных, записываемых в одной транзакции, ограничен. Подробности см. в разделе Ограничения при выполнении запросов.
Полный список ограничений системы приведён в Ограничения базы данных.