0

Модель и схема данных в Yandex Database, запросы и транзакции

26.04.2022

В этом уроке мы более подробно разберем, как в Yandex Database организованы данные, каких типов они могут быть, а также познакомимся с поддерживаемыми режимами транзакций.Модель и схема данныхYDB основана на реляционной модели данных. Это означает, что данные организованы в виде связанных друг с другом таблиц, которые состоят из столбцов и строк.Таблицы хранят записанную в БД информацию об объектах или сущностях. В столбцах таблицы записываются определенные типы данных, а в ячейках — значения. Каждая строка таблицы представляет собой набор связанных значений, относящихся к одному объекту или сущности.Таблица YDB всегда имеет один или несколько столбцов, являющихся первичным ключом (primary key). Первичный ключ представляет собой уникальный идентификатор строки, то есть для одного значения ключа может быть не больше одной строки. Допускаются таблицы, состоящие только из ключевых столбцов.Таблицы без первичного ключа создавать нельзя!В YDB таблицы всегда упорядочены по ключу. Это приводит к тому, что точечное чтение по ключу и диапазонные запросы по ключу или префиксу ключа фактически выполняются с использованием индекса, то есть с высокой эффективностью.Схема данных определяет имена (names) столбцов таблицы и то, какие типы данных (types) в них хранятся. Пример схемы данных приведен на рисунке.

image

Здесь изображена схема таблицы series, которая состоит из четырех столбцов с именами series_id, release_date, series_info и title. Первый столбец имеет тип данных Uint64, второй — Date, а последние два — Utf8. В качестве первичного ключа (PK) объявлен столбец series_id.Партиционирование таблицПервичный ключ также используется в YDB для партиционирования таблиц, то есть разбиения их на несколько частей. Каждая часть — партиция — включает отдельный диапазон первичных ключей, то есть диапазоны ключей, обслуживаемых разными партициями, не пересекаются.Партиции одной таблицы могут располагаться на разных, в том числе расположенных в разных локациях, хостах распределенной БД. Они могут перемещаться между хостами независимо друг от друга для перебалансировки данных и равномерного распределения нагрузки, а также для поддержания работоспособности партиции при отказах серверов или сетевых сбоях.Если данных немного, таблица может состоять из одной партиции. YDB автоматически разобьет партицию на две части, когда объем данных в ней или нагрузка увеличатся сверх определенного предела. Включение и выключение автоматического разделения можно настроить для каждой таблицы БД индивидуально.Помимо автоматического разделения таблиц на партиции YDB дает возможность создавать пустые таблицы с предопределённым количеством партиций. Для этого нужно либо задать границы диапазонов ключей вручную, либо указать, что таблица разделяется на заданное число партиций равномерно. В последнем случае границы диапазонов будут созданы по первой компоненте первичного ключа, которая должна быть целым числом.Типы данныхТип данных определяет множество значений, которые эти данные могут принимать, и то, какие операции можно выполнять со значениями. Например, данные логического типа (Bool) могут принимать значения true и false, и с ними можно выполнять логические операции И, ИЛИ, НЕ, ИСКЛЮЧАЮЩЕЕ ИЛИ, а также операции сравнения.Для работы с данными в YDB применяется декларативный язык запросов YQL (Yandex Query Language). Соответственно, в YDB можно использовать те типы данных, которые есть в YQL. Некоторые из типов данных YQL поддерживаются в YDB с ограничениями: они могут использоваться только в вычислениях, но не могут быть типом столбца или первичным ключом.Элементарными или примитивными типами данных называют такие, для которых значения нельзя разделить на несколько значений другого типа. К таким типам данных относят, например:

  • логический – Bool;
  • числовой – IntXX, UintXX, Float, Double (целые знаковые и беззнаковые числа, где XX показывает разрядность в битах; числа с плавающей точкой; числа двойной точности);
  • строковый – String, Utf8, Json, Uuid (произвольные бинарные данные, текст, форматы данных);
  • временной – Date, Datetime, Timestamp, Interval (дата, дата и время с точностью до секунд, временная отметка и интервал с точностью до микросекунд).

Композитные типы данных, или контейнеры, состоят из данных других элементарных или композитных типов. Такие типы данных в YQL включают:

  • список (List) – последовательность из 0 и более элементов одного типа. Количество элементов не фиксировано.
  • кортеж (Tuple) – упорядоченный набор из 0 и более элементов произвольных типов. Количество элементов фиксировано.
  • структуру (Struct) – именованный неупорядоченный набор из 0 или более элементов произвольных типов. Количество элементов фиксировано.
  • словарь (Dict) – набор пар ключ-значение. Все значения ключей уникальны. Все ключи имеют один и тот же тип, как и значения. Количество элементов не фиксировано.
  • опциональный тип (Optional) – последовательность из 0 или 1 элементов некоторого типа. Случай, когда в последовательности 0 элементов, изображается как NULL.
  • вариант (Variant) – подвид кортежа или структуры, в котором заполнен ровно один элемент.

Все столбцы, в том числе столбцы с первичным ключом, также могут содержать специальное значение NULL, которое используется, чтобы обозначить отсутствие значения.С полным перечнем типов данных, а также возможных операций над ними вы можете познакомиться в документации.Запросы и транзакцииОсновным средством добавления, обновления и удаления строк данных, извлечения наборов данных, а также управления работой БД в YDB является декларативный язык запросов YQL. Для выполнения YQL запросов можно использовать консоль управления Yandex.Cloud в браузере, консольный клиент для командной строки, а также SDK для различных языков программирования, которые позволяют встраивать запросы в приложения.Запрос – это команда на выполнение операции чтения или записи данных в БД. Например, запрос на чтение всех данных из таблицы будет выглядеть так:

Скопировать кодSELECT * FROM <имя таблицы> 

В одном из следующих практических уроков вы потренируетесь выполнять различные запросы к базе данных YDB.Транзакция – это несколько связанных запросов к БД, то есть последовательность операций чтения и записи данных, представляющая собой единую логическую задачу. Например, если вы перечисляете деньги с одного счета на другой, то с точки зрения работы с БД транзакция будет включать:

  • чтение данных о состоянии первого счета, чтобы проверить достаточно ли на нем средств;
  • уменьшение значения баланса этого счета на сумму перевода;
  • чтение данных о состоянии второго счета;
  • увеличение значения баланса этого счета на сумму перевода.

Транзакция будет выполнена только в том случае, если будут успешно завершены все операции, которые она включает.Транзакции в YDB по умолчанию выполняются в режиме Serializable. Это самый строгий уровень изоляции транзакций. Иными словами, в этом режиме гарантируется, что каждая транзакция полностью независима от других.Если требования к консистентности или свежести читаемых данных могут быть ослаблены (например, для повышения производительности БД, увеличения пропускной способности или уменьшения задержек), то пользователь может использовать режимы с менее строгими уровнями изоляции транзакций:

  • Online Read-Only – каждая из операций чтения в транзакции получает последние данные из имеющихся на момент выполнения. Консистентость полученных данных определяется настройкой allow_inconsistent_reads;
  • Stale Read Only – операции чтения данных возвращают результаты с возможным отставанием от актуальных (отставание составляет доли секунды). Для каждой отдельной операции чтения данные консистентны, но для разных операций чтения консистентность не гарантируется.

Поскольку таблицы в YDB могут быть партицированы, а отдельные партиции – храниться на разных шардах, YDB поддерживает распределенные транзакции, то есть транзакции, которые затрагивают более одного шарда одной или нескольких таблиц.А теперь давайте посмотрим, как YDB работает на практике.

Свежие комментарии

Подписка

Лучшие статьи


Fatal error: Uncaught Error: Call to a member function have_posts() on null in /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/inc/blog.php:380 Stack trace: #0 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/widgets/latest-posts/widget.php(257): fox56_blog_grid(NULL, Array) #1 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/widgets/latest-posts/register.php(33): include('/home/host18670...') #2 /home/host1867038/the-devops.ru/htdocs/www/wp-includes/class-wp-widget.php(394): Wi_Widget_Latest_Posts->widget(Array, Array) #3 /home/host1867038/the-devops.ru/htdocs/www/wp-includes/widgets.php(837): WP_Widget->display_callback(Array, Array) #4 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/inc/single.php(417): dynamic_sidebar('sidebar') #5 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/inc/single.php(136): fox56_single_sidebar() #6 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/inc/single.php(7): fox56_single_inner() #7 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/single.php(23): fox56_single() #8 /home/host1867038/the-devops.ru/htdocs/www/wp-includes/template-loader.php(106): include('/home/host18670...') #9 /home/host1867038/the-devops.ru/htdocs/www/wp-blog-header.php(19): require_once('/home/host18670...') #10 /home/host1867038/the-devops.ru/htdocs/www/index.php(17): require('/home/host18670...') #11 {main} thrown in /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/inc/blog.php on line 380