ブログ

【SAP HANA】手軽さとパフォーマンスに感動!WITH句を使わない階層データの作成について

この記事をSNSでシェア!

プロジェクトリーダーという役割上、主体となって開発作業を行うことは殆どないのですが、
SAP HANA Cloud以降 SAP HANAと表記)で、階層データ作成の検証を行う機会がありました。

所感ですが手軽さとパフォーマンスに感動。今回はその件について紹介します。

【参考】SAP HANAとは?

夜間バッチを使わない階層データを作成・取得方法を検証

今回私が検証したかったのはSAP HANAの環境で、労力をかけず階層データを作成・取得する方法です。

階層データの取り扱いは業務システムでは定番で、例えば過去に担当していた製造業の生産系システムではBOM(Bill Of Materials)、いわゆる部品表が一番身近な階層データでした。

製品を構成する部品は膨大な量となりますので、夜間バッチなどで品目テーブルから階層データ(部品表)を事前に作成し、日中のオンラインでアクセスするといったことが殆どです。

ですが今回は夜間バッチではなく、日中のオンラインでリアルタイムに階層データを作成・取得する仕組みが必要でした。

一番初めに思いつくのが常套手段として、下記のようなCTE(Common Table Expressions)で、WITH句を使った共通テーブル式です。

WITH recursive temp (n, fact) AS
(

     SELECT 0, 1
     UNION ALL
     SELECT n + 1, ( n + 1) * fact
     FROM temp
     WHERE n < 9
)
SELECT * FROM temp;

再帰的に問い合わせて階層を作るのですが、SAP HANAでは以下のエラーが発生してしまいました。

SQLエラー [259] [HY000]: SAP DBTech JDBC: [259] : invalid table name: Could not find table/view

調べてみると、公式ドキュメントでは「データセット内の再帰的な関係を表現する手段として、WITH RECURSIVE 共通テーブル式を提供します」と記述されていましたが、
反対に「HANAは再帰クエリ式をサポートできません」としているサイトもありました。

HANA DBでの階層データ作成について

公式ドキュメントをさらに読むと、
”データ セット内の再帰的な関係を表現する手段として、WITH RECURSIVE 共通テーブル式を提供します。おそらく、WITH RECURSIVE の実際の使用の大部分は SAP HANA の階層関数でカバーできますが・・・”とありました。つまり、SAP HANAでは階層にかかわる関数が標準で用意されているということです。

「そういえば過去に触ったSACDWCも階層を用いた分析やモデル作成ができたな。基盤はHANA DBだったし。」と思い出し、さっそくSAP HANAの階層関数(HIERARCHY Function)を使って実際に階層データが作成できるか確認してみました。

まずはテストデータの準備として、所属ID・所属名・親所属IDの3列からなる簡単な組織データを準備しました。

この組織データに対して階層データを作成するSQLを実行します。
ID(DEPT_CODE)と親ID(PARENT_DEPT_CODE)の列名を、それぞれNODE_ID・PARENT_IDとすることで階層関数が動作します。

SELECT
HIERARCHY_RANK,
HIERARCHY_TREE_SIZE,
HIERARCHY_PARENT_RANK,
HIERARCHY_LEVEL,
HIERARCHY_IS_CYCLE,
HIERARCHY_IS_ORPHAN,
NODE_ID,
DEPT_NAME,
PARENT_ID
FROM HIERARCHY (
SOURCE (
SELECT
DEPT_ID AS NODE_ID,
DEPT_NAME,
PARENT_DEPT_ID AS PARENT_ID
FROM TBL_TEST
)
) ORDER BY HIERARCHY_RANK;

実行後、以下の結果が取得できます。

簡単に階層データを作成できました。
各項目値の意味は以下になります。

意味
hierarchy_rank 連続した要素番号
hierarchy_tree_size 自身の配下に存在する子要素数
hierarchy_parent_rank 親要素の要素番号
hierarchy_level 自身が何階層目に属しているか
hierarchy_is_cycle 自身が循環しているか
hierarchy_is_orphan 自身が孤立しているか

更にこの結果をビューにしておけば、
他の階層関数を組み合わせてパス情報を付加することもできます。

先程実行したSQLをそのまま使って「V_HIERARCHY_TEST」というビューを作成しておき、下記のSQLを実行します。

SELECT
NODE_ID AS DEPT_ID,
PARENT_ID AS PARENT_DEPT_ID,
PATH,
HIERARCHY_LEVEL AS DEPT_LEVEL
FROM (
SELECT
HIERARCHY_LEVEL,
NODE_ID,
PARENT_ID,
‘/’ || PATH AS PATH
FROM HIERARCHY_ANCESTORS_AGGREGATE (
SOURCE V_HIERARCHY_TEST
MEASURES ( string_agg (DEPT_NAME, ‘/’ ) AS PATH ) )
ORDER BY NODE_ID
);

PATH列にて所属名をスラッシュで繋げることができました。
こちらも簡単ですね。

その他諸々の検証後、正規に開発した機能では、3万件程度とそこまで多くないデータ量とはいえ、
他テーブルや自身と結合した状態でもレスポンスに気を使うことはなく、非常に使いやすい階層データとなりました。

階層関数のパフォーマンスについて

インメモリデータベースであるHANA DBとMySQLを比較とすること自体ナンセンスではありますが、
大量データを使って、階層データの取得時間も確認してみました。
(MySQL側はWITH句を使ったCTEで処理)

MySQLはレコード件数が50万を超えると、15分経過してもレスポンスが無いにも関わらず、
HANA DBは100万件であろうが1秒を切るという結果になりました。

想定していた以上に速いです…。

複雑な構成で深い階層の大量データを扱う事案が発生した場合、改めて検証は必要ですが、このパフォーマンスはとても魅力的です。

最後に

WITH句を使った階層データ作成の試行がきっかけで、HANA DBの階層関数の存在を知ることができました。

階層関数は扱いに慣れれば、複雑なSQLを作成する手間も省け、積極的に使える機能だと感じましたし、とくにパフォーマンスに関しては「一度使ってみて!」と言いたくなるレベルです。

ちなみに階層関数はSAP HANAのコア機能として、様々な場面での利用を想定して、専用の開発ガイドも用意されています。(検証作業もこちらを参考に行いました)

【参考】 SAP HANA Hierarchy Developer Guide

今回はSAP HANAの一部分にしか触れていませんが、公式ページにあるように、
「できない事はないんじゃないの?」と思わされるほど様々な機能を備えています。

久しぶりに製品・機能の技術検証を行いましたが、やっぱり楽しいですね。

それではまた。

投稿者プロフィール

仙波 結城
仙波 結城
2004年入社。
汎用機運用から始まり、クラサバ・Webシステムの開発を経験。
2022年4月からSAP Business Technology Platform(SAP BTP)を基盤としたWEB開発業務のリーダーを担当しています。
この記事をSNSでシェア!