複雑なリレーションを前にSQLが「息切れ」するとき
10年以上のエンジニアキャリアの中で、私はMySQLやPostgreSQLからMongoDBまで、あらゆる種類のデータベースを扱ってきた。それぞれに得意分野があります。データ構造が厳格でACID特性が必要な場合、SQLは無敵です。しかし、現実は常に難題を突きつけてきます。例えば、50万人のユーザーを抱えるECサイトのレコメンデーションシステムを構築しているとしましょう。そこでは、顧客、商品、購買行動の間の関係がクモの巣のように複雑に絡み合っています。
このようなケースで純粋なSQLを使用すると、7〜8個のテーブルをJOINしたり、低速な再帰クエリ(Recursive CTE)に頼らざるを得なくなります。書き上げたクエリを見返すと、非常に複雑で頭が痛くなることでしょう。一般的な解決策はNeo4jのような専用のグラフデータベースを導入することですが、新たな管理システムを運用し、双方のデータを同期させることはインフラ面での悪夢となります。Apache AGEはまさにその課題を解決するために登場しました。PostgreSQLの内部にグラフのパワーを直接もたらすのです。
Apache AGEとは何か、なぜ注目すべきなのか?
Apache AGE (Graph Extension) は、PostgreSQLでグラフデータの理解と処理を可能にするApacheソフトウェア財団のプロジェクトです。並列で実行するのではなく、Postgresのカーネルに直接統合されます。最大のメリットは、openCypherをサポートしている点です。これは、リレーショナル界におけるSQLのように、現在最も普及しているグラフクエリ言語です。
私が最も素晴らしいと感じるのは、マルチモデル(Multi-model)クエリ機能です。従来のSQLテーブルから情報を取得しつつ、グラフクエリを組み合わせて潜在的なつながりを見つけ出すといったコマンドを一度に記述できます。例えば、「過去30日間に商品Xを購入した顧客Aの友人をすべて探す」といった操作が、データの不整合を心配することなく、単一のトランザクション内で完結します。
LinuxへのApache AGEインストールガイド
安定性を考慮し、ソースコードからのビルドをお勧めします。ここではUbuntuとPostgreSQL 15を使用します(AGEはバージョン11、12、13もサポートしています)。
1. 依存パッケージのインストール
まず、必要なコンパイルツールを準備します:
sudo apt-get update
sudo apt-get install build-essential libreadline-dev zlib1g-dev flex bison libssl-dev
2. Apache AGEソースコードのダウンロード
GitHubの公式リポジトリをクローンします:
git clone https://github.com/apache/age.git
cd age
3. コンパイルとインストール
PostgreSQLのpg_configファイルのパスを正しく指定する必要があります:
# お使いのマシンの正確なパスを確認してください
export PG_CONFIG=/usr/lib/postgresql/15/bin/pg_config
make install
エラーが表示されなければ、拡張機能の準備は完了です。
グラフ機能を有効化するためのPostgreSQL設定
インストールしただけではまだ使用できません。Postgresにいくつか「設定」を行う必要があります。
1. postgresql.confの設定ファイルを編集する
設定ファイル(通常は/etc/postgresql/15/main/postgresql.conf)を開き、shared_preload_librariesの行を探します:
shared_preload_libraries = 'age'
2. サービスの再起動
sudo systemctl restart postgresql
3. データベース内で拡張機能を初期化する
データベースにアクセスし、以下の初期化コマンドを実行します:
CREATE EXTENSION age;
LOAD 'age';
SET search_path = ag_catalog, "$user", public;
ag_catalogをsearch_pathに追加することで、AGEの関数を非常にスマートに呼び出せるようになります。
Cypherによるグラフクエリの実践
ここでは、実際にグラフデータの作成とクエリを行う方法を紹介します。
グラフ空間の作成
SELECT create_graph('itfromzero_network');
ノード(点)とリレーションシップ(辺)の作成
SQL内でグラフコマンドを実行するには、cypher()関数を使用します。例として、「Minh」という名前のエンジニアを作成します:
SELECT * FROM cypher('itfromzero_network', $$
CREATE (n:Person {name: 'Minh', role: 'Engineer'})
RETURN n
$$) as (v agtype);
2人の間に「Follow」リレーションを作成するには:
SELECT * FROM cypher('itfromzero_network', $$
MATCH (a:Person), (b:Person)
WHERE a.name = 'Minh' AND b.name = 'An'
CREATE (a)-[r:FOLLOWS]->(b)
RETURN r
$$) as (e agtype);
(a)-[:REL]->(b)という構文は、紙に図を描くのと同じように直感的で、無機質な外部キー管理よりもはるかに分かりやすいものです。
最適化と監視のノウハウ
AGEをプロダクション環境に導入する際は、システムのパフォーマンス低下を避けるために以下の点に注意してください:
- メモリ設定: グラフ演算はメモリを大量に消費します。
work_memをデフォルト(通常4MB)のままにすると、複雑なクエリは非常に低速になります。サーバーのリソースに応じて、64MBまたは256MBへの引き上げを検討してください。 - EXPLAIN ANALYZEの活用:
cypher()関数の外側でこのコマンドを実行してください。ノードスキャンのコストを分析し、「フルテーブルスキャン」が発生していないかを確認できます。 - インデックスの活用: AGEでは、グラフ属性に対してPostgresのGINまたはB-treeインデックスを使用できます。ノード内の
uidやslugといったフィールドへのインデックス作成を忘れないでください。
Apache AGEは、PostgreSQLの安定性を維持しつつ、複雑なデータ連携の処理能力を拡張したい人にとって素晴らしい選択肢です。高価で運用が難しいNoSQLのグラフデータベースへの移行を考える前に、ぜひAGEをインストールしてその利便性を体験してみてください。

