Как сделать памятку по родословной греческих богов в SAP HANA Cloud

В этом году у компании SAP появилось новое решение SAP HANA Cloud, которое предоставляет широкий спектр возможностей для работы с данными, позволяет создавать, запускать, развертывать новые и обновлять существующие приложения. Основу этого решения составляет SAP HANA, применяемая для работы с данными, требующими высокую скорость обработки. Мы называем такие данные горячими, поскольку они размещены в оперативной памяти. Это гарантирует быстрый доступ и высокую производительность. Кроме этого, в SAP HANA Cloud интегрировано озеро данных, и его развертывание происходит автоматически, а управление не вызывает затруднений. Оно реляционное и позволяет оптимизировать стоимость хранения структурированной информации. Там находятся холодные данные, то есть они будут обрабатываться несколько медленнее, чем горячие. SAP HANA Cloud предлагает и промежуточный уровень хранения данных — SAP HANA Native Storage Extension, хранение данных на диске и загрузка через буферный кеш. Возможности многоуровневого хранения обеспечивают высокий показатель масштабирования и эластичности, оптимизации затрат без ущерба для производительности. Предлагаю разобраться как работает новинка на примере создания родословной греческих богов и героев.

image

За основу возьмем скрипты из приложения Appendix B — Greek Mythology Graph Example документации SAP HANA Graph Reference для обычной платформы SAP HANA, которая развертывается локально в ЦОДе. Основное назначение этого примера — показать аналитические возможности SAP HANA, показать, как можно анализировать взаимосвязь объектов и событий с помощью алгоритмов работы с графами. Мы не будем останавливаться подробно на этой технологии, основная идея будет понятна из дальнейшего изложения. Кому интересно могут разобраться самостоятельно, испытав возможности SAP HANA express edition или пройти бесплатный курс Analyzing Connected Data with SAP HANA Graph.

Давайте разместим данные в реляционном облаке SAP HANA Cloud и посмотрим возможности по анализу родственных связей греческих героев. Помните, в «Мифах и легендах Древней Греции» было очень много персонажей и к середине уже не помнишь кто сын и брат кого? Вот мы сделаем себе памятку и никогда уже не забудем.

Для начала создадим экземпляр SAP HANA Cloud. Это сделать достаточно просто, надо заполнить параметры будущей системы и подождать несколько минут, пока экземпляр будет для вас развернут (рис. 1).

image
Рисунок 1

Итак, нажимаем кнопку Create Instance и перед нами открывается первая страница мастера создания, на которой надо указать краткое название экземпляра, задать пароль и привести описание (рис. 2)

image
Рисунок 2

Нажимаем кнопку Step 2, теперь наша задача указать параметры будущего экземпляра SAP HANA. Здесь можно задать только размер оперативной памяти будущей системы, все остальные параметры будут определены автоматически (рис. 3).

image
Рисунок 3

Мы видим, что сейчас у нас есть возможность выбрать минимальное значение 30Гб и максимальное 900Гб. Выбираем 30Гб и автоматически определяется, что при таком объеме памяти необходимо два виртуальных процессора для поддержки расчетов и 120Гб для хранения данных на диске. Здесь места выделяется больше, поскольку мы можем применять технологию SAP HANA Native Storage Extension (NSE). Если выбрать размер памяти больше, например, 255Гб, то потребуется уже 17 виртуальных процессоров и 720ГБ дисковой памяти (рис. 4).

image
Рисунок 4

Но нам столько памяти для примера не требуется. Возвращаем параметры в исходное значение и нажимаем Step 3. Теперь мы должны выбрать, будем ли использовать озеро данных. Для нас ответ очевиден. Конечно, будем. Именно такой эксперимент мы и хотим провести (рис. 5).

image
Рисунок 5

На этом шаге у нас значительно больше возможностей и свободы по созданию экземпляра озера данных. Вы можете выбирать размеры необходимых вычислительных ресурсов и дискового хранилища. Параметры используемых компонент/узлов выберутся автоматически. Система сама определит необходимые вычислительные ресурсы для «координатора» и «рабочих» узлов. Если вы хотите побольше узнать об этих компонентах, то лучше обратится к ресурсам SAP IQ и озеру данных SAP HANA Cloud. А мы двигаемся дальше, нажимаем Step 4 (рис. 6).

image
Рисунок 6

На этом шаге мы определим или ограничим IP адреса, которые могут получить доступ к будущему экземпляру SAP HANA. Как видим, это последний шаг нашего мастера (рис. 7), осталось нажать Create Instance и пойти налить себе кофе.

image
Рисунок 7

Процесс запущен и пройдет совсем немного времени, мы как раз успели выпить крепкого кофе, несмотря на позднюю ночь. А когда еще можно спокойно экспериментировать с системой и прикручивать разные фишки? Итак, наша система создана (рис. 8).

image
Рисунок 8

У нас есть два варианта: открыть SAP HANA Cockpit или SAP HANA Database Explorer. Мы знаем, что запустить второй продукт можно будет из Cockpit. Поэтому открываем SAP HANA Cockpit, заодно и посмотрим, что там есть. Но сначала необходимо будет указать пользователя и его пароль. Обратите внимание, что пользователь SYSTEM вам недоступен, вы должны применять DBADMIN. При этом указать пароль, который вы задали при создании экземпляра, как на рис. 9.

image
Рисунок 9

Мы зашли в Cockpit и видим традиционный интерфейс SAP в виде плиточек, когда каждая из них отвечает за свою задачу. Справа в верхнем углу видим ссылку на SQL Console (рис. 10).

image
Рисунок 10

Именно она нам позволяет перейти к SAP HANA Database Explorer.

image

Интерфейс этого инструмента похож на SAP Web IDE, но предназначен только для работы с объектами базы данных. В первую очередь, конечно, нас интересует как попасть в озеро данных. Ведь сейчас мы открыли инструмент для работы с HANA. Перейдем в навигаторе на пункт Remote Source и увидим ссылку на озеро (SYSRDL, RDL — Relation Data Lake). Вот он желанный доступ (рис. 11).

image
Рисунок 11

Двинемся дальше, мы же не должны работать под администратором. Нужно создать тестового пользователя, под которым проведем эксперимент с графовым движком HANA, но данные разместим в реляционном озере данных.

image
Рисунок 12

СКРИПТ:

CREATE USER tstuser PASSWORD Password1 NO FORCE_FIRST_PASSWORD_CHANGE SET USERGROUP DEFAULT;


Мы планируем работать с озером данных, поэтому надо обязательно дать права, например, HANA_SYSRDL#CG_ADMIN_ROLE, чтобы можно свободно создавать объекты, делать все, что нам вздумается.

image

СКРИПТ:

GRANT HANA_SYSRDL#CG_ADMIN_ROLE TO tstuser;


Теперь работа под администратором SAP HANA завершена, SAP HANA Database Explorer можно закрыть и нам надо войти в него под новым созданным пользователем: tstuser. Для простоты, вернемся в SAP HANA Cockpit и завершим сессию администратора. Для этого в левом верхнем углу есть такая ссылка Clear Credentials (рис. 12).

image
Рисунок 12

После нажатия на нее нам снова надо войти в систему, но теперь под пользователем tstuser (рис. 13).

image
Рисунок 13

И мы снова можем открыть SQL Console, чтобы вернуться в SAP HANA Database Explorer, но под новым пользователем (рис. 14).

image

image
Рисунок 14

СКРИПТ:

SELECT SESSION_USER, CURRENT_SCHEMA FROM DUMMY;


Все, теперь мы уверены, что работаем с HANA под нужным пользователем. Пора создавать таблицы в озере данных. Для этого есть специальная процедура SYSRDL#CG.REMOTE_EXECUTE, в которую надо передать один параметр — строку = команду. Используя, эту функцию создаем в озере данных таблицу (рис. 15), в которой будут хранится все наши персонажи: герои, греческие Боги и титаны.

image
Рисунок 15

СКРИПТ:

CALL SYSRDL#CG.REMOTE_EXECUTE ('
BEGIN

	CREATE TABLE "MEMBERS" (
		"NAME"       VARCHAR(100) PRIMARY KEY,
		"TYPE"       VARCHAR(100),
		"RESIDENCE"  VARCHAR(100)
	);


END');


И затем создаем таблицу в которой будем хранить родственные связи этих персонажей (рис. 16).

image
Рисунок 16

СКРИПТ:

CALL SYSRDL#CG.REMOTE_EXECUTE ('
BEGIN
	CREATE TABLE "RELATIONSHIPS" (
		"KEY"    INTEGER UNIQUE NOT NULL,
		"SOURCE" VARCHAR(100) NOT NULL,
		"TARGET" VARCHAR(100) NOT NULL,
		"TYPE"   VARCHAR(100),
		FOREIGN KEY RELATION_SOURCE ("SOURCE") references "MEMBERS"("NAME") ON UPDATE RESTRICT ON DELETE RESTRICT, 
		FOREIGN KEY RELATION_TARGET ("TARGET") references "MEMBERS"("NAME") ON UPDATE RESTRICT ON DELETE RESTRICT 
	);
END');


Мы не будем сейчас заниматься вопросами интеграции, это отдельная история. В исходном примере есть команды INSERT для создания греческих Богов и их родственных отношений. Используем эти команды. Надо только помнить, что команду мы передаем через процедуру в озеро данных, поэтому надо кавычки удвоить, как показано на рис. 17.

image
Рисунок 17

СКРИПТ:

CALL SYSRDL#CG.REMOTE_EXECUTE ('
BEGIN
	INSERT INTO "MEMBERS"("NAME", "TYPE")
    	VALUES (''Chaos'', ''primordial deity'');
	INSERT INTO "MEMBERS"("NAME", "TYPE")
    	VALUES (''Gaia'', ''primordial deity'');
	INSERT INTO "MEMBERS"("NAME", "TYPE")
    	VALUES (''Uranus'', ''primordial deity'');
	INSERT INTO "MEMBERS"("NAME", "TYPE", "RESIDENCE")
    	VALUES (''Rhea'', ''titan'', ''Tartarus'');
	INSERT INTO "MEMBERS"("NAME", "TYPE", "RESIDENCE")
    	VALUES (''Cronus'', ''titan'', ''Tartarus'');
	INSERT INTO "MEMBERS"("NAME", "TYPE", "RESIDENCE")
    	VALUES (''Zeus'', ''god'', ''Olympus'');
	INSERT INTO "MEMBERS"("NAME", "TYPE", "RESIDENCE")
    	VALUES (''Poseidon'', ''god'', ''Olympus'');
	INSERT INTO "MEMBERS"("NAME", "TYPE", "RESIDENCE")
    	VALUES (''Hades'', ''god'', ''Underworld'');
	INSERT INTO "MEMBERS"("NAME", "TYPE", "RESIDENCE")
    	VALUES (''Hera'', ''god'', ''Olympus'');
	INSERT INTO "MEMBERS"("NAME", "TYPE", "RESIDENCE")
    	VALUES (''Demeter'', ''god'', ''Olympus'');
	INSERT INTO "MEMBERS"("NAME", "TYPE", "RESIDENCE")
    	VALUES (''Athena'', ''god'', ''Olympus'');
	INSERT INTO "MEMBERS"("NAME", "TYPE", "RESIDENCE")
    	VALUES (''Ares'', ''god'', ''Olympus'');
	INSERT INTO "MEMBERS"("NAME", "TYPE", "RESIDENCE")
    	VALUES (''Aphrodite'', ''god'', ''Olympus'');
	INSERT INTO "MEMBERS"("NAME", "TYPE", "RESIDENCE")
    	VALUES (''Hephaestus'', ''god'', ''Olympus'');
	INSERT INTO "MEMBERS"("NAME", "TYPE", "RESIDENCE")
    	VALUES (''Persephone'', ''god'', ''Underworld'');
END');


И вторая таблица (рис. 18)

image
Рисунок 18

СКРИПТ:

CALL SYSRDL#CG.REMOTE_EXECUTE ('
BEGIN
	INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    	VALUES (1, ''Chaos'', ''Gaia'', ''hasDaughter'');
	INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    	VALUES (2, ''Gaia'', ''Uranus'', ''hasSon'');
	INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    	VALUES (3, ''Gaia'', ''Cronus'', ''hasSon'');
	INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    	VALUES (4, ''Uranus'', ''Cronus'', ''hasSon'');
	INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    	VALUES (5, ''Gaia'', ''Rhea'', ''hasDaughter'');
	INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (6, ''Uranus'', ''Rhea'', ''hasDaughter'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (7, ''Cronus'', ''Zeus'', ''hasSon'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (8, ''Rhea'', ''Zeus'', ''hasSon'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (9, ''Cronus'', ''Hera'', ''hasDaughter'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (10, ''Rhea'', ''Hera'', ''hasDaughter'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (11, ''Cronus'', ''Demeter'', ''hasDaughter'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (12, ''Rhea'', ''Demeter'', ''hasDaughter'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (13, ''Cronus'', ''Poseidon'', ''hasSon'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (14, ''Rhea'', ''Poseidon'', ''hasSon'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (15, ''Cronus'', ''Hades'', ''hasSon'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (16, ''Rhea'', ''Hades'', ''hasSon'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (17, ''Zeus'', ''Athena'', ''hasDaughter'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (18, ''Zeus'', ''Ares'', ''hasSon'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (19, ''Hera'', ''Ares'', ''hasSon'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (20, ''Uranus'', ''Aphrodite'', ''hasDaughter'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (21, ''Zeus'', ''Hephaestus'', ''hasSon'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (22, ''Hera'', ''Hephaestus'', ''hasSon'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (23, ''Zeus'', ''Persephone'', ''hasDaughter'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (24, ''Demeter'', ''Persephone'', ''hasDaughter'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (25, ''Zeus'', ''Hera'', ''marriedTo'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (26, ''Hera'', ''Zeus'', ''marriedTo'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (27, ''Hades'', ''Persephone'', ''marriedTo'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (28, ''Persephone'', ''Hades'', ''marriedTo'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (29, ''Aphrodite'', ''Hephaestus'', ''marriedTo'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (30, ''Hephaestus'', ''Aphrodite'', ''marriedTo'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (31, ''Cronus'', ''Rhea'', ''marriedTo'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (32, ''Rhea'', ''Cronus'', ''marriedTo'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (33, ''Uranus'', ''Gaia'', ''marriedTo'');
INSERT INTO "RELATIONSHIPS"("KEY", "SOURCE", "TARGET", "TYPE")
    VALUES (34, ''Gaia'', ''Uranus'', ''marriedTo'');
END');


Откроем теперь снова Remote Source. Нам надо на основании описания таблиц в озере данных создать виртуальные таблицы в HANA (рис. 19).

image
Рисунок 19

Находим обе таблицы, устанавливаем «галочки» напротив таблиц и нажимаем кнопку Create Virtual Object (s), как показано на рис. 20.

image
Рисунок 20

У нас есть возможность указать схему, в которой виртуальные таблицы будут созданы. И там надо указать префикс, чтобы эти таблицы легче было найти. После этого мы можем в навигаторе выбрать Table, увидеть наши таблицы и посмотреть данные (рис. 21).

image
Рисунок 21

На этом шаге важно обратить внимание на фильтр внизу слева. Там должно быть указано имя нашего пользователя или наша схема TSTUSER.

Вот почти все готово. Мы создали в озере таблицы и загрузили в них данные, а для доступа к ним с уровня HANA у нас есть виртуальные таблицы. Мы готовы создать новый объект — граф (рис. 22).

image
Рисунок 22

СКРИПТ:

CREATE GRAPH WORKSPACE "GREEK_MYTHOLOGY"
  EDGE TABLE "TSTUSER"."RDL_RELATIONSHIPS"
    SOURCE COLUMN "SOURCE"
    TARGET COLUMN "TARGET"
    KEY COLUMN "KEY"
  VERTEX TABLE "TSTUSER"."RDL_MEMBERS"
    KEY COLUMN "NAME";


Все сработало, граф готов. И сразу можно попробовать сделать какой-нибудь простой запрос к данным графа, например, найти всех дочерей Хаоса и всех дочерей этих дочерей. Для этого нам поможет Cypher — язык для анализа графов. Он был специально создан для работы с графами, удобный, простой и помогает решать сложные задачи. Нам только надо помнить, что скрипт Cypher надо обернуть в SQL запрос с помощью табличной функции. Посмотрите, как на этом языке решается наша задача (рис. 23).

image
Рисунок 23

СКРИПТ:

SELECT * FROM OPENCYPHER_TABLE( GRAPH WORKSPACE "GREEK_MYTHOLOGY" QUERY
    '
	MATCH p = (a)-[*1..2]->(b)
	WHERE a.NAME = ''Chaos'' AND ALL(e IN RELATIONSHIPS(p) WHERE e.TYPE=''hasDaughter'')
	RETURN b.NAME AS Name
	ORDER BY b.NAME
    '
)


Проверим, как работает визуальный инструмент SAP HANA для анализа графов. Для этого в навигаторе выберем Graph Workspace (рис. 24).

image
Рисунок 24

И теперь можно увидеть наш граф (рис. 25).

image
Рисунок 25

Вы видите уже «раскрашенный» граф. Это мы сделали с помощью настроек в правой стороне экрана. Слева в верхнем углу показывается детальная информация по узлу, который в данный момент выделен.

Что ж… Мы сделали это. Данные находятся в озере данных, а их анализ мы проводим инструментами в SAP HANA. Одна технология вычисляет данные, а другая отвечает за их хранение. Когда происходит обработка данных графа, они запрашиваются из озера данных и передаются в SAP HANA. Можем ли мы ускорить наши запросы? Как сделать так, чтобы данные хранились в оперативной памяти и не подгружались из озера данных? Есть простой, но не очень красивый способ — создать таблицу, в которую загрузить содержимое таблицы озера данных (рис. 26).

image
Рисунок 26

СКРИПТ:

CREATE COLUMN TABLE MEMBERS AS (SELECT * FROM "TSTUSER"."RDL_MEMBERS")


Но есть еще один способ — это применение репликации данных в оперативную память SAP HANA. Это может обеспечить лучшую производительность запросов SQL, чем доступ к данным, размещенным в озере данных с помощью виртуальной таблицы. Вы можете переключаться между виртуальными и таблицами репликации. Для этого необходимо к виртуальной таблице добавить таблицу реплики. Это можно сделать с помощью инструкции ALTER VIRTUAL TABLE. После чего, запрос, использующий виртуальную таблицу, автоматически обращается к таблице реплик, которая размещается в оперативной памяти SAP HANA. Давайте посмотрим, как это сделать, проведем эксперимент. Выполним такой запрос (рис. 27).

image
Рисунок 27

СКРИПТ:

SELECT R.KEY, R.SOURCE, R.TYPE
FROM "TSTUSER"."RDL_RELATIONSHIPS"  R inner join "TSTUSER"."MEMBERS" M on R.SOURCE=M.NAME


И посмотрим, сколько надо было времени, чтобы выполнить этот запрос (рис. 28).

image

Мы видим, потребовалось 92 миллисекунды. Давайте включим механизм репликации. Для этого надо сделать ALTER VIRTUAL TABLE виртуальной таблицы, после чего данные Озера будут реплицированы в оперативную память SAP HANA.

image
Рисунок 28

СКРИПТ:

ALTER VIRTUAL TABLE "RDL_RELATIONSHIPS" ADD SHARED SNAPSHOT REPLICA COLUMN LOADABLE;


Проверим время выполнения, как на рисунке 29.

image
Рисунок 29

Получили 7 миллисекунд. Это отличный результат! Минимальными усилиями мы переместили данные в оперативную память. Причем, если вы закончили анализ и вас устроит производительность, можно снова отключить репликацию (рис. 30).

image
Рисунок 30

СКРИПТ:

ALTER VIRTUAL TABLE "RDL_RELATIONSHIPS" DROP REPLICA;


Теперь данные опять подгружаются из Озера только по запросу, а оперативная память SAP HANA свободна для новых задач. Сегодня мы выполнили, на мой взгляд, интересную работу и протестировали SAP HANA Cloud на быстроту, легкую организацию единой точки доступа к данным. Продукт будет развиваться, и мы ожидаем, что в ближайшее время может появится прямое соединение с озером данных. Новая возможность обеспечит более высокую скорость загрузки больших объемов информации, отказ от ненужных служебных данных и повышение производительности операций, специфичных для озера данных. Мы будем создавать и выполнять хранимые процедуры непосредственно в облаке данных на технологии SAP IQ, то есть сможем применять обработку и бизнес-логику там, где находятся сами данные.

Александр Тарасов, старший бизнес-архитектор SAP CIS

© Habrahabr.ru