Быстрый старт с YDB

В этом руководстве вы установите одноузловой локальный кластер YDB и выполните простые запросы к вашей базе данных.

Обычно YDB хранит данные напрямую на нескольких дисковых устройствах SSD/NVMe или HDD без использования файловой системы. Однако для простоты данное руководство эмулирует диски в оперативной памяти или с использованием файла в обычной файловой системе. Таким образом, эта конфигурация не подходит для использования в промышленном окружении и даже для проведения тестов производительности. Ознакомьтесь с документацией для DevOps-инженеров для запуска YDB в production окружении.

Установите и запустите YDB

Примечание

Рекомендуемая среда для запуска YDB - это x86_64 Linux. Если у вас нет доступа к такой системе, можете переключиться на инструкции во вкладке "Docker".

  1. Создайте каталог для тестирования YDB и используйте его в качестве текущего рабочего каталога:

    mkdir ~/ydbd && cd ~/ydbd
    
  2. Загрузите и запустите скрипт установки:

    curl https://install.ydb.tech | bash
    

    Это действие загрузит и распакует архив с исполняемым файлом ydbd, библиотеками, файлами конфигурации и скриптами, необходимыми для запуска и остановки локального кластера.

    Скрипт выполняется с текущими привилегиями пользователя (обратите внимание на отсутствие sudo). Таким образом, он не может сделать многого в системе. Чтобы проверить какие именно команды он выполняет — откройте этот же URL в вашем браузере.

  3. Запустите кластер в одном из следующих режимов хранения данных:

    • Данные в оперативной памяти:

      ./start.sh ram
      

      В этом случае все данные хранятся только в оперативной памяти, и они будут потеряны при остановке кластера.

    • Данные в файле на диске:

      ./start.sh disk
      

      При первом запуске скрипта будет создан файл ydb.data размером 80 ГБ в рабочем каталоге. Убедитесь, что у вас достаточно свободного места на диске для его создания. Этот файл будет использоваться для эмуляции дискового устройства, которое использовалось бы в промышленном окружении.

    • Данные на дисковом устройстве:

      ./start.sh drive "/dev/$DRIVE_NAME"
      

      Замените /dev/$DRIVE_NAME на настоящее имя устройства, которое не используется для других целей, например /dev/sdb. В первый раз при запуске этой команды указанный дисковый накопитель будет полностью очищен, а затем будет подключен для хранения данных YDB. Рекомендуется использовать NVMe или SSD-диск с объемом не менее 800 Гб. Такая конфигурация может быть использована для тестирования производительности на одном узле или других сред, которые не имеют каких-либо требований к отказоустойчивости.

    Результат:

    Starting storage process...
    Initializing storage ...
    Registering database ...
    Starting database process...
    
    Database started. Connection options for YDB CLI:
    
    -e grpc://localhost:2136 -d /Root/test
    
  1. Создайте каталог для тестирования YDB и используйте его в качестве текущего рабочего каталога:

    mkdir ~/ydbd && cd ~/ydbd
    mkdir ydb_data
    mkdir ydb_certs
    
  2. Запустите Docker-контейнер:

    docker run -d --rm --name ydb-local -h localhost \
      --platform linux/amd64 \
      -p 2135:2135 -p 2136:2136 -p 8765:8765 -p 9092:9092 \
      -v $(pwd)/ydb_certs:/ydb_certs -v $(pwd)/ydb_data:/ydb_data \
      -e GRPC_TLS_PORT=2135 -e GRPC_PORT=2136 -e MON_PORT=8765 \
      -e YDB_KAFKA_PROXY_PORT=9092 \
      ydbplatform/local-ydb:latest
    

    Если контейнер успешно запустился, вы увидите его идентификатор. Контейнеру может потребоваться несколько секунд для инициализации. База данных будет недоступна до окончания инициализации.

    Примечание

    При использовании Mac с процессором Apple Silicon, набор процессорных инструкций x86_64 можно эмулировать с помощью Rosetta:

    • colima c параметрами colima start --arch aarch64 --vm-type=vz --vz-rosetta;
    • Docker Desktop с установленной и включённой Rosetta 2.
  1. Установите интерфейс командной строки Kubernetes kubectl и менеджер пакетов Helm 3.

  2. Установите и запустите Minikube.

  3. Склонируйте репозиторий с YDB Kubernetes Operator:

    git clone https://github.com/ydb-platform/ydb-kubernetes-operator && cd ydb-kubernetes-operator
    
  4. Установите на кластер контроллер YDB:

    helm upgrade --install ydb-operator deploy/ydb-operator --set metrics.enabled=false
    
  5. Примените манифест для создания кластера YDB:

    kubectl apply -f samples/minikube/storage.yaml
    
  6. Подождите, пока kubectl get storages.ydb.tech станет Ready.

  7. Примените манифест для создания базы данных:

    kubectl apply -f samples/minikube/database.yaml
    
  8. Подождите, пока kubectl get databases.ydb.tech станет Ready.

  9. После обработки манифеста создаётся объект StatefulSet, описывающий набор динамических узлов. Созданная база данных будет доступна изнутри кластера Kubernetes по DNS-имени database-minikube-sample на портах 2135 и 8765.

  10. Получите доступ к порту 8765 снаружи Kubernetes через kubectl port-forward database-minikube-sample-0 8765 для продолжения.

  1. Установите интерфейс командной строки Kubernetes kubectl и менеджер пакетов Helm 3.

  2. Установите Kind.

  3. Склонируйте репозиторий с YDB Kubernetes Operator:

    git clone https://github.com/ydb-platform/ydb-kubernetes-operator && cd ydb-kubernetes-operator
    
  4. Создайте Kind кластер и дождитесь его готовности:

    kind create cluster --config=samples/kind/kind-config.yaml  --wait 5m
    
  5. Установите на кластер контроллер YDB:

    helm upgrade --install ydb-operator deploy/ydb-operator --set metrics.enabled=false
    
  6. Примените манифест для создания хранилища данных YDB:

    kubectl apply -f samples/kind/storage.yaml
    
  7. Подождите, пока kubectl get storages.ydb.tech станет Ready.

  8. Примените манифест для создания базы данных:

    kubectl apply -f samples/kind/database.yaml
    
  9. Подождите, пока kubectl get databases.ydb.tech станет Ready.

  10. После обработки манифеста создаётся объект StatefulSet, описывающий набор динамических узлов. Созданная база данных будет доступна изнутри кластера Kubernetes по DNS-имени database-kind-sample на портах 2135 и 8765.

  11. Получите доступ к порту 8765 снаружи Kubernetes через kubectl port-forward database-kind-sample-0 8765 для продолжения.

Запустите первый запрос "Hello, world!"

Самый простой способ выполнить свой первый запрос к YDB - это встроенный веб-интерфейс. Он запускается по умолчанию на порту 8765 сервера YDB, поэтому, если вы запустили его локально, вам нужно открыть localhost:8765 в вашем веб-браузере. Если нет, замените localhost на имя хоста вашего сервера в этом URL, либо используйте ssh -L 8765:localhost:8765 my-server-hostname-or-ip.example.com для настройки проброса порта и все равно откройте localhost:8765. Вы увидите страницу подобного вида:

Стартовая страница веб-интерфейса

YDB спроектирован как многопользовательская система с возможностью одновременной работы тысяч пользователей с одним кластером. Как следствие, большинство логических сущностей внутри кластера YDB находятся в гибкой иерархической структуре, больше похожей на виртуальную файловую систему Unix, чем на схему с фиксированной глубиной, с которой вы, возможно, знакомы из других систем управления базами данных. Как видите, первый уровень иерархии состоит из баз данных, работающих в одном процессе YDB, которые могут принадлежать разным пользователям. /Root предназначена для системных целей, а /Root/test или /local (имя зависит от выбранного способа установки) - это «игровая площадка», созданная в процессе установки на предыдущем шаге. Давайте нажмём на последнюю, /Root/test или /local, затем введем наш первый запрос и нажмем кнопку запуска:

SELECT "Hello, world!"u;

Запрос возвращает приветствие, как и задумано:

SELECT "Hello, world!"u;

Примечание

Заметили странный суффикс u? YDB и её язык запросов YQL являются строго типизированными. Обычные строки в YDB могут содержать любые двоичные данные, в то время как этот суффикс указывает, что этот литерал имеет тип данных Utf8, который может содержать только валидные последовательности UTF-8. Узнайте больше о системе типов YDB.

Второй по простоте способ выполнения SQL-запроса с использованием YDB - это интерфейс командной строки (CLI). Большинство реальных приложений же, скорее всего, будут работать с YDB через один из доступных наборов инструментов для разработчиков программного обеспечения (SDK). Если вы чувствуете себя уверенно — можете продолжить прохождение данного руководства с помощью одного из этих методов вместо веб-интерфейса.

Создайте свою первую таблицу

Основная цель существования систем управления базами данных - сохранение данных для последующего извлечения. Как система, базирующаяся на SQL, основной абстракцией YDB для хранения данных является таблица. Чтобы создать нашу первую таблицу, выполните следующий запрос:

CREATE TABLE example
(
    key UInt64,
    value String,
    PRIMARY KEY (key)
);

Как видите, это простая таблица ключ-значение. Давайте пройдемся по ней пошагово:

  • Каждый тип оператора SQL вроде CREATE TABLE имеет подробное описание в справке по YQL.
  • example - это идентификатор имени таблицы, а key и value - идентификаторы имен столбцов. Рекомендуется использовать простые имена для таких идентификаторов, но если вам нужно использовать имя с необычными символами, оберните его в обратные кавычки.
  • UInt64 и String - это названия типов данных. String представляет собой двоичную строку, а UInt64 - 64-разрядное беззнаковое целое число. Таким образом, наша таблица-пример хранит строковые значения, идентифицируемые беззнаковыми целочисленными ключами. Подробнее о типах данных.
  • PRIMARY KEY - одно из основных понятий SQL, которое оказывает огромное влияние на логику приложения и производительность. В соответствии со стандартом SQL, первичный ключ также подразумевает ограничение уникальности, поэтому таблица не может иметь несколько строк с одинаковыми первичными ключами. В этой примерной таблице довольно просто определить, какой столбец пользователь должен выбрать в качестве первичного ключа, и мы указываем его как (key) в круглых скобках после соответствующего ключевого слова. В реальных сценариях таблицы часто содержат десятки столбцов, и первичные ключи могут быть составными (состоять из нескольких столбцов в указанном порядке), поэтому выбор правильного первичного ключа становится больше похожим на искусство. Если вас интересует эта тема, есть руководство по выбору первичного ключа для максимизации производительности. YDB таблицы обязаны иметь первичный ключ.

Добавление тестовых данных

Теперь давайте заполним нашу таблицу первыми данными. Самый простой способ - использовать литералы:

INSERT INTO example (key, value)
VALUES (123, "hello"),
       (321, "world");

Пошаговое описание:

  • INSERT INTO - это классический оператор SQL для добавления новых строк в таблицу. Однако он не является наиболее производительным, так как согласно стандарту SQL он должен проверить, существуют ли в таблице строки с заданными значениями первичного ключа, и выдать ошибку, если они уже есть. Таким образом, если вы запустите этот запрос несколько раз, все попытки, кроме первой, вернут ошибку. Если логика вашего приложения не требует такого поведения, лучше использовать UPSERT INTO вместо INSERT INTO. Upsert (от "update or insert") будет безусловно записывать предоставленные значения, перезаписывая существующие строки, если они есть. Остальной синтаксис будет таким же.
  • (key, value) указывает имена столбцов, которые мы вставляем, и их порядок. Предоставленные значения должны соответствовать этому описанию как по количеству столбцов, так и по их типам данных.
  • После ключевого слова VALUES следует список кортежей, каждый из которых представляет собой строку таблицы. В этом примере у нас есть две строки, идентифицируемые числами 123 и 321 в столбце key, и значениями "hello" и "world" в столбце value соответственно.

Чтобы убедиться, что строки были действительно добавлены в таблицу, существует распространённый запрос, который в данном случае должен вернуть 2:

SELECT COUNT(*) FROM example;

Несколько деталей в этом запросе:

  • Во FROM указывают таблицу, из которой извлекаются данные.
  • COUNT - это агрегатная функция, подсчитывающая количество значений. По умолчанию, когда нет других специальных выражений вокруг, наличие любой агрегатной функции приводит к сворачиванию результата в одну строку, содержащую агрегаты по всему входным данным (таблице example в данном случае).
  • Астериск * является спецсимволом, который обычно означает "все столбцы"; таким образом, COUNT вернет общее количество число строк.

Еще один распространённый способ заполнить таблицу данными - это объединить операции INSERT INTO (или UPSERT INTO) и SELECT. В этом случае значения для сохранения вычисляются внутри базы данных, а не предоставляются клиентом в виде литералов. Для демонстрации этого подхода мы используем немного более реалистичный запрос:

$subquery = SELECT ListFromRange(1000, 10000) AS keys;

UPSERT INTO example
SELECT
    key,
    CAST(RandomUuid(key) AS String) AS value
FROM $subquery
FLATTEN LIST BY keys AS key

В этом запросе происходит немало интересного, давайте рассмотрим его подробнее:

  • $subquery - это именованное выражение. Этот синтаксис является расширением YQL по сравнению со стандартным SQL и позволяет делать более читаемые сложные запросы. Он работает так же, как если бы вы написали первый SELECT по месту, где $subquery используется в последней строке. Однако, использование именованных выражений позволяет легче понять, что происходит шаг за шагом, подобно переменным в обычных языках программирования.

  • ListFromRange - это функция, которая создает список последовательных целых чисел, начиная с значения, указанного в первом аргументе, и заканчивая значением, указанным во втором аргументе. Также есть третий необязательный аргумент, который позволяет пропускать числа с указанным шагом, но мы не используем его в нашем примере — по умолчанию возвращаются все целые числа в указанном диапазоне. List является одним из наиболее распространенных контейнерных типов данных.

  • AS - это ключевое слово, используемое для задания имени значения, которое мы возвращаем из SELECT; в данном примере - keys.

  • В части FROM ... FLATTEN LIST BY ... AS ... есть несколько значимых моментов:

    • Другой SELECT, использованный в выражении FROM, называется подзапросом. Поэтому мы выбрали это имя для нашего именованного выражения $subquery, но мы могли бы выбрать что-то более значимое, чтобы объяснить, что это такое. Подзапросы обычно не материализуются; они просто передают вывод одного SELECT вводу другого на лету. Они могут использоваться в качестве средства для создания произвольно сложных графов выполнения, особенно в сочетании с другими возможностями YQL.
    • Ключевая фраза FLATTEN LIST BY изменяет входные данные, передаваемые через FROM, следующим образом: для каждой строки во входных данных она берет столбец типа данных List и создает несколько строк в соответствии с количеством элементов в этом списке. Обычно этот столбец списка заменяется столбцом с текущим одиночным элементом, но ключевое слово AS в данном контексте позволяет получить доступ и ко всему списку (по исходному имени) и текущему элементу (по имени после AS).
  • RandomUuid - это функция, которая возвращает псевдослучайный UUID версии 4. В отличие от большинства других функций, она не использует значение своего аргумента (столбец key); вместо этого этот аргумент указывает на то, что нам нужно вызывать функцию для каждой строки. Смотрите ссылку с дополнительными примерами работы этой функции.

  • CAST(... AS ...) - это часто используемая функция для преобразования значений в указанный тип данных. В этом контексте после AS ожидается указание типа данных (в данном случае String), а не произвольного имени.

  • UPSERT INTO слепо записывает значения в указанные таблицы, как мы обсуждали ранее. При использовании в сочетании с SELECT он не требует явного указания имен столбцов (key, value), так как столбцы теперь могут быть просто сопоставлены по именам, возвращённым из SELECT.

Короткий вопрос!

Что теперь вернёт запрос SELECT COUNT(*) FROM example;?

Остановка кластера

Остановите локальный кластер YDB после завершения экспериментов:

Чтобы остановить локальный кластер, выполните следующую команду:

~/ydbd/stop.sh

При желании вы можете удалить вашу рабочую директорию с помощью команды rm -rf ~/ydbd для очистки файловой системы. Все данные внутри локального кластера YDB будут потеряны.

Чтобы остановить Docker контейнер с локальным кластером, выполните следующую команду:

docker kill ydb-local

При желании вы можете удалить вашу рабочую директорию с помощью команды rm -rf ~/ydbd для очистки файловой системы. Все данные внутри локального кластера YDB будут потеряны.

Чтобы удалить базу данных YDB, достаточно удалить сопоставленный с ней ресурс Database:

kubectl delete database.ydb.tech database-minikube-sample

Чтобы удалить кластерYDB, выполните следующие команды (все данные будут потеряны):

kubectl delete storage.ydb.tech storage-minikube-sample

Чтобы удалить контроллер YDB из кластера Kubernetes, удалите релиз, созданный Helm:

helm delete ydb-operator

Чтобы удалить базу данных YDB, достаточно удалить сопоставленный с ней ресурс Database:

kubectl delete database.ydb.tech database-kind-sample

Чтобы удалить кластер YDB, выполните следующие команды (все данные будут потеряны):

kubectl delete storage.ydb.tech storage-kind-sample

Чтобы удалить контроллер YDB из кластера Kubernetes, удалите релиз, созданный Helm:

helm delete ydb-operator

Чтобы удалить кластер Kind целиком, выполните следующую команду:

kind delete cluster

Готово! Что дальше?

После освоения базовых операций из этого руководства, пора переходить перейти к более глубоким темам. Выберите то, что кажется наиболее актуальным в зависимости от вашего сценария использования и роли:

Предыдущая
Следующая