OLAP多次元セマンティックモデルの基礎

概要

本稿では、OLAP(Online Analytical Processing)多次元セマンティックモデルの基本概念と実装方法について解説します。

OLAPは、OLTP(Online Transaction Processing)と対比される概念です。厳密に言えば、OLAPと多次元データ構造は必ずしも関連がありません。関係モデル、グラフモデル、時系列モデルなど、様々なデータモデルに基づくオンライン分析がOLAPと呼ばれます。しかし、多くのOLAPシステムが多次元モデリングのアプローチを採用しているため、OLAPと多次元データ構造は密接に関連しています。

セマンティックモデルとは、MySQLやHiveのようなデータベースシステムが、底層のストレージ構造(B+TreeやHDFS)とは異なる、より高レベルなデータモデル(テーブルやカラムのような関係モデル)を提供する層を指します。

ここで言うOLAP多次元セマンティックモデルとは、OLAPシステムが、その底層のストレージ構造(星型構造、スノーフレーク構造、ワイドテーブルなど)に関わらず、論理レベルで純粋な多次元モデルを正確に記述する能力を持つ場合を指します。これはSQL、MDX、プログラミングインターフェースなどを通じて実現されます。

本稿では、Dockerを使用してOLAP多次元データベース環境を構築し、実践的な例を通じて各概念を説明します。まずはDocker環境を準備してください。

OLAP多次元セマンティックモデルに関連する主要な概念を以下の表にまとめました。現時点では全体像を把握する程度で構いません。各概念の詳細は後続のセクションで説明します。

td>
概念 英語 説明
次元 Dimension ビジネスの観点を表し、データを分類・グループ化するために使用されます。
メンバー Member 次元内の具体的な要素を指し、特定のデータポイントを表します。
多次元データセット Cube 複数の次元を関連付けることで論理的なN次元立方体構造を形成し、多角的な分析を可能にします。
測定値 Measure多次元データセット内で分析される数値であり、売上高や利益などの重要な指標を表します。
セット Set タプルの集合体で、多次元クエリ結果における次元の具体的な表示情報を定義するために使用されます。
タプル Tuple 複数の次元メンバーから構成され、多次元データセット内のデータポイントを表します。
レベル Level 階層構造内の特定の層を指し、メンバーの粒度や詳細度を表します(例:時間次元における年、四半期、月)。
階層構造 Hierarchy 次元内のメンバー間の親子関係に基づいて形成される木構造です。
次元ロール Dimension Role ある次元が複数回Cubeに関連付けられる場合、そのCube上で異なる役割を果たします。

OLAP環境の準備

Dockerエンジンがインストールされたサーバーを準備し、以下のコマンドを実行してOLAP多次元データベースサービスを実行するDockerコンテナを起動します。

$ docker run -d -p 8760:8760 --name olapdb olapdb/olap:latest

Pythonを使用してこのOLAPデータベースに接続します。ローカルのPython環境からコンテナ内のOLAPデータベースに接続します。

ローカルPythonからOLAPデータベースに接続

以下のコマンドを実行して、PyOLAPライブラリとrequestsパッケージをインストールします。

$ pip install pyolap-analysis && pip install requests

ローカルのPythonインタラクティブ環境に入り、以下のコードをコピーして実行します。エラーが発生しなければ正常に接続されています。

# pyolap-analysisパッケージのolapモジュールをインポート
from pyolap-analysis import olap

# olapdb多次元データベースサービスに接続
# IPアドレスはDockerコンテナを実行しているサーバーのIPに変更してください!!!
olap_connection = olap.OlapConnection("192.168.1.100", 8760)

# 接続を閉じる
olap_connection.close()

次元(Dimension)

次元はOLAP多次元モデルにおいて最も重要な概念の一つです。特定のビジネスの観点を表し、例えば電子商取引プラットフォームの売上データを分析する場合、日付、地域、商品、支払方法などのビジネス観点が考えられます。

データウェアハウスシステムを構築する際には、通常星型テーブル構造が採用されます。OLAP多次元セマンティックモデルの次元オブジェクトは、星型構造における次元テーブルと見なすことができます。

ここでは、多次元データセットモデルを一から構築し、そのモデルに基づいてデータ分析を行います。このCubeは電子商取引プラットフォームの売上データモデルで、日付、地域、商品、支払方法の4つの次元に関連付けられます。以下のPythonコードを実行してこれら4つの次元オブジェクトを作成します。

from pyolap-analysis import olap

# コンテナ内のPython環境を使用する場合はIPアドレスを127.0.0.1に設定!!!
# ローカルPythonを使用する場合はDockerコンテナを実行しているサーバーのIPに変更してください!!!
olap_connection = olap.OlapConnection("192.168.1.100", 8760)

# create_dimensionsメソッドはDimensionクラスのインスタンスのリストを返します
dimensions = olap_connection.create_dimensions("日付", "地域", "商品", "支払方法")

for dim in dimensions:
    print(f"{type(dim)} - [{dim.name}]次元が作成されました")

olap_connection.close()

メンバー(Member)

次元が次元テーブルと見なされるならば、メンバーは次元テーブル内のレコードと見なすことができます。

前の手順で4つの次元オブジェクトを作成しましたが、これらは空のテーブルです。次に、これら4つの次元に対応するメンバーを作成します。これは次元テーブルにレコードを挿入する操作に相当します。

from pyolap-analysis import olap

date_members = [
    ["2023", "Q1", "M1"],
    ["2023", "Q1", "M2"],
    ["2023", "Q1", "M3"],
    ["2023", "Q2", "M4"],
    ["2023", "Q2", "M5"],
    ["2023", "Q2", "M6"],
    ["2023", "Q3", "M7"],
    ["2023", "Q3", "M8"],
    ["2023", "Q3", "M9"],
    ["2023", "Q4", "M10"],
    ["2023", "Q4", "M11"],
    ["2023", "Q4", "M12"]
]

region_members = ["東京", "大阪", "名古屋", "札幌", "福岡", "横浜", "京都", "神戸"]

goods_members = [
    ["ゲーム機器", "PS"],
    ["ゲーム機器", "XBOX"],
    ["ゲーム機器", "Switch"],
    ["スポーツ用品", "マウンテンバイク"],
    ["スポーツ用品", "カヤック"],
    ["スポーツ用品", "サッカーボール"]
]

payment_members = ["クレジットカード", "PayPay", "銀行振込"]

# コンテナ内のPython環境を使用する場合はIPアドレスを127.0.0.1に設定!!!
# ローカルPythonを使用する場合はDockerコンテナを実行しているサーバーのIPに変更してください!!!
olap_connection = olap.OlapConnection("192.168.1.100", 8760)

date_dim = olap_connection.get_dimension_by_name("日付")
date_dim.create_members(date_members)

region_dim = olap_connection.get_dimension_by_name("地域")
region_dim.create_members(region_members)

goods_dim = olap_connection.get_dimension_by_name("商品")
goods_dim.create_members(goods_members)

payment_dim = olap_connection.get_dimension_by_name("支払方法")
payment_dim.create_members(payment_members)

olap_connection.close()

次元内のメンバーは、その間の親子関係に基づいて木構造を形成します。商品次元を例にすると、以下のような構造になります。

図のように、商品次元のメンバーはROOTメンバーを根として木構造を形成します。このROOTは商品次元オブジェクトが作成された際にシステムによって自動的に作成され、作成した商品次元のメンバーはすべてこのROOTの下に配置されます。

多次元データセット(Cube)と測定値(Measure)

前の2つのステップで次元を作成し、各次元に次元メンバーを追加しました。これらの操作は、次元テーブルを作成し、次元テーブルにデータを追加する操作に相当します。

次にCubeオブジェクトを作成します。これは事実データテーブルを作成する操作に相当します。

from pyolap-analysis import olap

# コンテナ内のPython環境を使用する場合はIPアドレスを127.0.0.1に設定!!!
# ローカルPythonを使用する場合はDockerコンテナを実行しているサーバーのIPに変更してください!!!
olap_connection = olap.OlapConnection("192.168.1.100", 8760)

date_dim = olap_connection.get_dimension_by_name("日付")
region_dim = olap_connection.get_dimension_by_name("地域")
goods_dim = olap_connection.get_dimension_by_name("商品")
payment_dim = olap_connection.get_dimension_by_name("支払方法")

cube = olap_connection.build_cube("eコマース販売モデル",
                               [date_dim, region_dim, goods_dim, payment_dim],
                               ["売上額", "販売数量"])

olap_connection.close()

olap_connectionのbuild_cubeメソッドを呼び出す際に3つのパラメータを渡しています。最初のは多次元データセットの名前、2つ目はこのCubeに関連付ける次元のリスト、3つ目のパラメータリストはこのCubeが持つ2つの測定値(売上額と販売数量)を指定しています。これは、double型の測定値フィールドを持つ事実データテーブルを作成する操作に相当します。

これまでに、次元(Dimension)と次元メンバー(Member)を作成し、多次元データセット(Cube)を構築し、測定値(Measure)を指定しました。これらの操作は、ROLAP星型モデルの次元テーブルと事実テーブルを作成する操作に相当します。ただし、事実テーブルはまだ空です。事実テーブルにデータを挿入すれば、多次元分析が可能になります。

以下のPythonコードを実行して、Cubeに測定値データを追加します。これはROLAP事実テーブルに測定値レコードを挿入する操作に相当します。

import requests
from pyolap-analysis import olap

data_url = "https://example.com/ecommerce_sales_data.txt"
response = requests.get(data_url)
response.encoding = "UTF8"

# コンテナ内のPython環境を使用する場合はIPアドレスを127.0.0.1に設定!!!
# ローカルPythonを使用する場合はDockerコンテナを実行しているサーバーのIPに変更してください!!!
olap_connection = olap.OlapConnection("192.168.1.100", 8760)

olap_connection.execute(response.text)

olap_connection.close()

これで、完全な多次元データセットモデルの構築が完了しました。ここまでの作業を振り返ると、以下の通りです。

  • まず次元を作成し、これはROLAP星型モデルの次元テーブルを作成する操作に相当します。
  • 次に次元メンバーを作成し、これは次元テーブルにレコードを追加する操作に相当します。
  • 次にCubeを構築し測定値を指定し、これは事実データテーブルを作成する操作に相当します。
  • 最後にCubeに測定値データを追加し、これは事実テーブルに測定値レコードを挿入する操作に相当します。

モデル構築の作業は完了しました。他の概念を説明する前に、このCubeに基づいていくつかの典型的な多次元クエリを実行してみましょう。

多次元データ分析

まず、2023年の各四半期の売上額と販売数量データをクエリしてみましょう。以下のPythonコードを実行します:

from pyolap-analysis import olap
from pyolap-analysis.olap import QueryBuilder

# コンテナ内のPython環境を使用する場合はIPアドレスを127.0.0.1に設定!!!
# ローカルPythonを使用する場合はDockerコンテナを実行しているサーバーのIPに変更してください!!!
olap_connection = olap.OlapConnection("192.168.1.100", 8760)

query_builder = QueryBuilder()\
    .from_cube("eコマース販売モデル")\
    .set_rows("[Measures].members()")\
    .set_columns("[日付].[2023].children()")

result = olap_connection.query(query_builder)

print(result)

olap_connection.close()

地域、商品、支払方法の3つの次元で制限をかけなかったため、返されたデータはこれら3つの次元で自動的に集計されています。

多次元モデルの作成、測定値データの追加、そして多次元クエリの実行という簡単なプロセスが完了しました。今後の記事では、他の多次元セマンティックモデルの概念についても紹介していきます。

タグ: OLAP 多次元データベース データウェアハウス データ分析 Python

6月23日 21:05 投稿