Тарификация YDB в бессерверном режиме
Кратко:
- В бессерверном режиме YDB тарифицируется за исполнение запросов к БД и хранение данных.
- Хранение данных: объем хранилища serverless БД условно бесконечен, тарификация с точностью до 1 КБ.
- Исполнение запросов: оценка в Request Units (RU), стоимость зависит от использованных ресурсов.
- Free tier: хранение менее 1 ГБ данных бесплатно, расчет стоимости от 1 ГБ в месяц.
- Тариф "за фактическое потребление": 21,38 рублей за 1 миллион RU, применяется после превышения 1 миллиона RU.
- Выделенная пропускная способность: ограничение на потребление RU в секунду, экономия при постоянной нагрузке.
- Расчет стоимости запросов через YQL, DocumentAPI и специализированные API.
Тарификация YDB в бессерверном режиме
Из предыдущих уроков вы уже знаете, что сервисы в группе Бессерверные вычисления тарифицируются по-своему. Давайте разберёмся с тем, как рассчитывается стоимость использования YDB.
В бессерверном режиме YDB вы платите за исполнение запросов к БД и хранение данных. Кроме того, тарифицируется использование других сервисов (например, объектного хранилища для резервных копий «по требованию», или исходящий трафик из Yandex Cloud в интернет). Но в этой части начислений нет какой-либо serverless-специфики, поэтому мы не будем на них останавливаться в рамках этого курса.
Хранение данных
Начнём с того, о чем можно рассказать быстро, — стоимости хранения данных. В отличие от dedicated режима, где вы оплачиваете зарезервированное под ваши данные дисковое пространство, объём хранилища serverless БД условно бесконечен и никак не влияет на стоимость. В полном соответствии с концепцией serverless, вы платите только за тот объём, который фактически используете. Также, пока объём ваших данных меньше 1 ГБ, их хранение будет бесплатно (Free tier).
Тариф устанавливается за хранение 1 ГБ в месяц выше бесплатного порога, расчет производится с точностью до 1 КБ. Таким образом, по действующему на момент написания этого урока тарифу в 21,38 рублей хранение 2,5 ГБ данных обойдется вам в 32,07 рублей в месяц.
Исполнение запросов
Исполнение любого запроса к БД оценивается в специальной единице измерения, которая называется Request Unit (сокращенно RU). Она отражает, сколько различных ресурсов было задействовано для исполнения запроса. Чем больше ресурсов потребовалось, тем выше стоимость исполнения запроса в Request Units (RU) и, соответственно, конечная стоимость в рублях.
Для каждого вида запросов определены правила, по которым на основании собираемой в процессе исполнения запроса информации об использовании ресурсов определяется его стоимость в RU. Данные правила нужно понимать для того, чтобы представлять какие ресурсы требуются для исполнения разных запросов, как их использование влияет на стоимость, и выбирать наиболее оптимальный вариант их исполнения.
Чтобы предотвратить неожиданное использование большого количества RU из-за неоптимальных запросов, может быть установлено ограничение по потреблению RU в секунду. По умолчанию для каждой создаваемой БД устанавливается ограничение в 10 RU/сек, к которому применяется накопление неиспользованных RU в течение 5 минут. С таким ограничением вы можете свободно вести разработку и тестирование приложений, не опасаясь получить большой незапланированный счет.
Суммарная стоимость исполнения всех запросов в RU за некоторый период является базой, на основании которой рассчитывается стоимость в рублях, с применением следующих правил тарификации:
- Первый миллион Request Units каждый месяц предоставляется бесплатно (Free tier).
- Если стоимость исполненных запросов превысила 1 миллион RU, то далее действует тариф «за фактическое потребление» (on-demand), составляющий на момент написания этого курса 21,38 рублей за 1 миллион RU, применяемый с точностью до 1 RU.
- Вы можете установить специальный параметр БД, который называется «выделенная пропускная способность» (provisioned capacity) и измеряется в RU/сек. Если данный параметр больше нуля, то вы перейдёте на почасовое начисление оплаты за пропускную способность в указанных пределах. Она рассчитывается по специальному тарифу, стоимость RU на котором существенно ниже чем на тарифе «за фактическое потребление». Стоимость исполненных запросов в пределах установленной выделенной пропускной способности (с учетом пятиминутного накопления неиспользованных RU) будет вычитаться из суммирования по тарифу on-demand, что позволяет существенно сэкономить, если нагрузка на ваше приложение более-менее постоянна.
- Если вы установили значение параметра «выделенная пропускная способность» равное параметру «ограничение пропускной способности», то получите точную стоимость в рублях в месяц вне зависимости от вашей нагрузки. Такой режим похож на работу с выделенными ресурсами, но отличается от них тем, что ограничения можно в любой момент изменить, а минимальный квант в 1 RU/сек будет стоить вам 7.2 рубля в месяц по тарифам, актуальным на момент подготовки этого урока. При этом, за счет накопления неиспользуемых RU в течение 5 минут, на таком ограничении вы можете успешно исполнять запросы стоимостью до 300 RU один раз в 5 минут.
Далее мы познакомим вас с правилами расчета стоимости запроса в Request Units для разных типов запросов:
- YQL
- DocumentAPI
- Специальные API
Правила расчета стоимости запросов через YQL
YQL — диалект SQL, который используется для работы с данными, представленными в виде реляционных таблиц. Вы познакомились с ним в курсе «Хранение и анализ данных».
Давайте рассмотрим пример вычисления стоимости запроса, объединяющего данные из двух таблиц, которые вы создавали, работая с YDB в dedicated режиме.
SELECT
sa.title AS season_title,
sr.title AS series_title,
sr.series_id,
sa.season_id
FROM
seasons AS sa
INNER JOIN
series AS sr
ON sa.series_id = sr.series_id
WHERE sa.series_id = 1
ORDER BY
sr.series_id,
sa.season_id
;

Для того, чтобы определить стоимость выполнения этого запроса, перейдите на вкладку Стоимость. Вы увидите, что стоимость запроса составила 6 RU.
Теперь давайте рассмотрим статистику выполнения этого запроса и определим, из чего складывается стоимость.

Как вы можете видеть, статистика запроса содержит следующую информацию:
{
"processCpuTimeUs": "8367",
"queryPhases": [
{
"affectedShards": "2",
"cpuTimeUs": "948",
"durationUs": "40606",
"tableAccess": [
{
"name": "series",
"partitionsCount": "1",
"reads": {
"bytes": "16",
"rows": "1"
}
},
{
"name": "seasons",
"partitionsCount": "1",
"reads": {
"bytes": "96",
"rows": "4"
}
}
]
}
]
}
Где:
query_phases[].cpu_time_us
— время CPU на выполнение запроса в мкс.compilation.cpu_time_us
— время CPU на компиляцию запроса в мкс.process_cpu_time_us
— время CPU на управление взаимодействием в мкс.query_phases[].reads.rows
— число прочитанных записей данных.query_phases[].reads.bytes
— число прочитанных байт данных.query_phases[].updates.rows
— число записанных записей данных.query_phases[].updates.bytes
— число записанных байт данных.
Для определения стоимости запроса через YDB API вычисляются стоимость использования CPU и стоимость ввода-вывода данных. Из вычисленных значений выбирается максимальное.
Расчет стоимости использования CPU
Суммируется время CPU, затраченное на компиляцию запроса, а также время использования CPU на всех этапах его выполнения. Сумма делится на продолжительность одного окна 1,5 мс, округляется в меньшую сторону и переводится в RU по тарифу из таблицы, с которой можно познакомиться в документации.
Чтобы получить стоимость использования CPU, сумма времени CPU запроса делится на 1,5 мс.
(8367+948)/1500=6,21.
Результат округляется в меньшую сторону и переводится в RU:
6∗1 RU = 6 RU
Стоимость ввода-вывода данных
Рассчитываются следующие значения:
-
Количество операций чтения с диска. Сравнивается число прочитанных записей и блоков данных, выбирается наибольшее из них. Число блоков вычисляется делением суммы прочитанных байт на размер блока 4 КБ, с округлением вверх.
-
Количество операций записи на диск. Сравнивается число записанных записей и блоков данных, выбирается наибольшее из них. Число блоков вычисляется делением суммы записанных байт на размер блока 1 КБ, с округлением вверх.
Учитывается ввод-вывод данных в таблицы и индексы. При удалении записей учитывается только их количество.
Количества операций чтения и записи переводятся в RU по тарифу из таблицы, с которой можно познакомиться в документации, полученные стоимости складываются.
Чтобы получить стоимости ввода-вывода данных, вычисляется количество операций чтения с диска в записях и блоках, из них выбирается максимальное:
-
прочитаны 5 записей, количество операций равно 5;
-
прочитаны 112 байт,112/(4×1024)=0,027,результат округляется в большую сторону, количество операций равно 1.
Количество операций чтения равно 5.
Стоимость ввода-вывода:
5×1 RU = 5 RU
Стоимость выполнения запроса равна 6 RU, так как на CPU затрачено больше ресурсов.
Правила расчета стоимости запроса через DocumentAPI
Об этих правилах вы узнаете на следующем уроке, когда будете знакомиться с DocumentAPI.
Правила расчета стоимости запроса через специализированные API
Существует несколько специализированных API, расчет RU для которых делается по отдельным правилам:
- ReadTable — специальная операция, предназначенная для считывания больших объемов данных. Её оценка в RU зависит только от объема данных и составляет 128 RU за 1 МБ, с округлением вверх до ближайшего мегабайта.
- BulkUpsert — специальная операция, предназначенная для вставки больших объемов данных в БД. Её оценка в RU зависит только от объема данных и составляет 0,5 RU за 1 КБ данных, с округлением вверх до ближайшего килобайта.
Проверьте себя
Рассчитайте стоимость следующего запроса YQL. Ответ введите в текстовое поле ниже.
$to_update = (
SELECT series_id,
season_id,
episode_id,
Utf8("Yesterday's Jam UPDATED") AS title
FROM episodes
WHERE series_id = 1 AND season_id = 1 AND episode_id = 1
);
SELECT * FROM episodes WHERE series_id = 1 AND season_id = 1;
UPDATE episodes ON
SELECT * FROM $to_update;
На основании статистики запроса:
{
"processCpuTimeUs": "11254",
"queryPhases": [
{
"affectedShards": "1",
"cpuTimeUs": "590",
"durationUs": "8939",
"tableAccess": [
{
"name": "episodes",
"partitionsCount": "1",
"reads": {
"bytes": "24",
"rows": "1"
}
}
]
},
{
"affectedShards": "1",
"cpuTimeUs": "510",
"durationUs": "4131",
"tableAccess": [
{
"name": "episodes",
"partitionsCount": "1",
"reads": {
"bytes": "48",
"rows": "2"
}
}
]
},
{
"affectedShards": "1",
"cpuTimeUs": "380",
"durationUs": "4056",
"tableAccess": [
{
"name": "episodes",
"partitionsCount": "1",
"reads": {
"bytes": "257",
"rows": "6"
}
}
]
},
{
"affectedShards": "1",
"cpuTimeUs": "463",
"durationUs": "8651",
"tableAccess": [
{
"name": "episodes",
"partitionsCount": "1",
"updates": {
"bytes": "47",
"rows": "1"
}
}
]
}
]
}
Сколько получилось?
Правильный ответ:
- 11