はじめに
この記事はOCI上でのリソースの作成から、サーバーへ接続してグラフを作成してクエリまでを実行してみました。
Analyze, Query, and Visualize Graphs in Oracle Database Workshop の記事を参考にOCI上でAutonomous Databaseと接続したGraph Serverを作成しています。
また、今回利用するリソースはOCIの無料トライアル環境でも構築可能な内容になっています。
前提条件
-OCIのアカウントを持っていること
-ssh接続のための秘密鍵と公開鍵を持っていること
上記2点は元記事のGetting StartedおよびLab1:Create SSH Keysで確認可能ですが、基本的な点のため、今回は割愛します。
今回の構成
Autonomous DatabaseとOCIマーケットプレイスからプロビジョニングできるグラフサーバーを利用します。
Autonomous Databaseを作成する
1.Oracle Cloudにログインする
2.ログイン後、左側のメニューから Oracle Database > Autonomous Databaseをクリックします。
3. Autonomous Databaseの作成ボタンを押して、作成画面へ移動します。
4. 基本的な情報を入力します
-
コンパートメント: 任意のコンパートメントを選択してください
-
表示名: ATPGraph(お好きな覚えやすい名前で大丈夫です)
-
データベース名: ATPGRAPH (条件に合ったお好きな覚えやすい名前で大丈夫です)
-
ワークロードタイプ: トランザクション処理(データウェアハウスでも特に問題はないです)
-
データベース・バージョンの選択:19cか21cを選択
-
OCPU数:利用したいCPUの数を選びます。(1でも今回のラボでは問題はありません)
無料環境の場合はAlways Freeの構成オプションのみを表示というボタンがあるので活用してください。( 1 CPU と 20 GBが選択可能なはずです。) -
OCPUの自動スケーリング:今回はオフにします
-
パスワード:条件に合う任意のものを設定
-
ネットワークアクセスの選択:すべての場所からのセキュア・アクセスを選択
-
ライセンス・タイプの選択:ライセンス込みを選択(すでにライセンスをお持ちの場合はBYOLを選択可能です)
問題がなければ上記内容で左下のAutonomous Databaseの作成をクリックします。
数分間でプロビジョニングが完了します。
プロビジョニング中は黄色い画面で、完了すると緑色の画面になります
グラフサーバーを作成する
このグラフサーバーを作成するステップでは
- グラフサーバーを構成するためのネットワークの作成
- OCIマーケットプレイスからサーバーのデプロイ
- グラフサーバーがADBと接続するためのウォレットの構成
までの操作を行います。
ネットワークを作成
1.VCNウィザードを利用して、基本的なネットワーキングに必要なリソースを作成します。
OCIのメニュー画面から、ネットワーキング>仮想クラウド・ネットワーク をクリックします
仮想クラウド・ネットワークのトップ画面で、VCNウィザードの起動を選択します
するとVCNウィザードの起動の詳細画面が出るので、インターネット接続性を持つVCNの作成を選択して、左下のVCNウィーザードの起動ボタンをクリックします。
ウィザード起動後、構成画面に移動するので、VCN名のみ任意のものに設定し、そのほかの設定はデフォルトのままにして、次へボタンをクリックして作成を完了させます。
準備ができ次第、ネットワークが完成します。
2.ネットワークでグラフ接続のためのポートを開放する
グラフサーバーは7007番ポートを利用して通信を行うため、先ほど作成したネットワークのポートを開放します。
ポートの開放は、メニューバーのネットワーキング>仮想クラウドネットワークの画面に移動して、先ほど作成したネットワークをクリックします。(名前の例はvcn1ですが、画像ではseoulvcnとなっています)
VCNの詳細画面が表示されるので、ここでパブリック・サブネットをクリックします。
デフォルトセキュリティリストを選択し
イングレス・ルールの詳細画面から、イングレス・ルールの追加ボタンを選択して、
下記のイングレスルールを追加します。
- ソース・タイプ: CIDR
- ソースCIDR: 0.0.0.0/0 (テスト環境のみ推奨、実際の環境では任意のソースに置き換えてください)
- IPプロトコル: TCP
- ソース・ポート範囲: All
- 宛先ポート範囲: 7007
-
説明: For Graph Server
これで7007番ポートも通信可能となりました。
マーケットプレイスからグラフサーバーを作成する
マーケットプレイスイメージを活用することで、ユースケースに応じて必要なソフトウェアがデプロイ後すぐに使い始めることができます。
-
スタックが起動されたら、特に変更せずに次へボタンを押す
-
変数の構成画面では下記の設定を入力
- 任意のリソース名、コンパートメントとAvailability Domein
- 任意のシェイプ(Always freeプランではVM.Standard.E2.1.Microが選択可)
- SSH公開鍵を貼り付ける
- ネットワークでは前のステップで作成したネットワークを指定(vcn1)
- JDBC URL: jdbc:oracle:thin:@atpgraph_low?TNS_ADMIN=/etc/oracle/graph/wallets
※入力するJDBC URLの意味について
これはこの後のステップで、グラフサーバーにアップロードする予定のAutonomous Databaseの認証用ウォレットを置く予定のディレクトリへのTNS_ADMINのエントリーポイントです。
データベース名を例で示されているatpgraphとは違う名前で命名した場合は、置き換えてください。(myatpgraphというデータベース名の場合、@myatpgraph_lowにURLの例を置き換える)
設定項目を入力後、次へを押して、作成を開始します。完了すると緑色の画面に変わります。2,3分程度で完了される予定です。
※Always-free Compute VM は、ホームリージョンにのみ作成できます。以前にalways-free compute VMを作成している場合は、以前のVMと同じアベイラビリティドメインのみに新たなVMインスタンスを作成することが可能なため、エラー時にはご確認ください。
- スタックを閉じる前にアクセスに必要になるpublicipとgraphvizpublic_urlの値をログからメモしてください
ADBウォレットをダウンロード
-
パスワードを入力して、zip形式のウォレットをダウンロード
ウォレットをダウンロードする時にはe** データベース作成時に指定したパスワード** の入力が求められるので入力します。
デフォルトのファイル名は Wallet_.zipです
ADBウォレットをグラフサーバーにアップロード
サーバーにファイルをアップロードする方式はほかにもありますが、ここではscpを利用してダウンロードしたウォレットをグラフサーバーにアップロードします。
-
サーバーにウォレットをアップロード
scp -i <private_key> <Wallet_database_name>.zip opc@<public_ip_for_compute>:/etc/oracle/graph/wallets 例) scp -i key.pem ~/Downloads/Wallet_ATPGRAPH.zip opc@203.0.113.14:/etc/oracle/graph/wallets
-
アップロード済のウォレットを解凍する
グラフサーバーにSSHでopcユーザーとして、秘密鍵を指定してアクセスしますssh -i <private_key> opc@<public_ip_for_compute> 例) ssh -i key.pem opc@203.0.113.14
-
ADBウォレットを /etc/oracle/graph/wallets/ ディレクトリで解凍します
cd /etc/oracle/graph/wallets/ unzip Wallet_ATPGRAPH.zip chgrp oraclegraph *
-
正しいJDBC URLをOCIのコンピュート作成時に入力しているかを必要であれば確認します
cat /etc/oracle/graph/wallets/tnsnames.ora
正しければ下記のような値を確認できるはずです
atpgraph_low =
(description=
(address=
(https_proxy=proxyhostname)(https_proxy_port=80)(protocol=tcps)(port=1521)
(host=adwc.example.oraclecloud.com)
)
(connect_data=(service_name=adwc1_low.adwc.oraclecloud.com))
(security=(ssl_server_cert_dn="adwc.example.oraclecloud.com,OU=Oracle BMCS US,O=Oracle Corporation,L=Redwood City,ST=California,C=US"))
)
グラフを利用可能なユーザーを作成する
graph関連の権限を作成する
graphを作成するためには別途GRAPH_DEVELOPERやGRAPH_ADMINISTRATOR等の権限が必要になります。
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
role_exists EXCEPTION;
PRAGMA EXCEPTION_INIT(role_exists, -01921);
TYPE graph_roles_table IS TABLE OF VARCHAR2(50);
graph_roles graph_roles_table;
BEGIN
graph_roles := graph_roles_table(
'GRAPH_DEVELOPER',
'GRAPH_ADMINISTRATOR',
'GRAPH_USER',
'PGX_SESSION_CREATE',
'PGX_SERVER_GET_INFO',
'PGX_SERVER_MANAGE',
'PGX_SESSION_READ_MODEL',
'PGX_SESSION_MODIFY_MODEL',
'PGX_SESSION_NEW_GRAPH',
'PGX_SESSION_GET_PUBLISHED_GRAPH',
'PGX_SESSION_COMPILE_ALGORITHM',
'PGX_SESSION_ADD_PUBLISHED_GRAPH');
FOR elem IN 1 .. graph_roles.count LOOP
BEGIN
dbms_output.put_line('create_graph_roles: ' || elem || ': CREATE ROLE ' || graph_roles(elem));
EXECUTE IMMEDIATE 'CREATE ROLE ' || graph_roles(elem);
EXCEPTION
WHEN role_exists THEN
dbms_output.put_line('create_graph_roles: role already exists. continue');
WHEN OTHERS THEN
RAISE;
END;
END LOOP;
EXCEPTION
when others then
dbms_output.put_line('create_graph_roles: hit error ');
raise;
END;
/
GRANT PGX_SESSION_CREATE TO GRAPH_ADMINISTRATOR;
GRANT PGX_SERVER_GET_INFO TO GRAPH_ADMINISTRATOR;
GRANT PGX_SERVER_MANAGE TO GRAPH_ADMINISTRATOR;
GRANT PGX_SESSION_CREATE TO GRAPH_DEVELOPER;
GRANT PGX_SESSION_NEW_GRAPH TO GRAPH_DEVELOPER;
GRANT PGX_SESSION_GET_PUBLISHED_GRAPH TO GRAPH_DEVELOPER;
GRANT PGX_SESSION_MODIFY_MODEL TO GRAPH_DEVELOPER;
GRANT PGX_SESSION_READ_MODEL TO GRAPH_DEVELOPER;
GRANT PGX_SESSION_CREATE TO GRAPH_USER;
GRANT PGX_SESSION_GET_PUBLISHED_GRAPH TO GRAPH_USER;
これでグラフに関する権限を設定することができました。
新規ユーザーを作成
データベースアクションズ画面から、新たにCUSTOMER_360というユーザーを作成します。
下記内容を指定します。
- ユーザー名:CUSTOMER_360
- 任意のパスワード
- グラフ: 有効化
- Webアクセス: 有効化
- 表領域の割り当て制限 :UNLIMITED
- 付与されたロール: GRAPH_DEVELOPER role と PGX_SESSION_ADD_PUBLISHED_GRAPH を追加
下記画面のPGX_SESSION_ADD_PUBLISHED_GRAPHグラフロールがないと、作成したグラフを永続化させる権限を持たないユーザーになるので、付与する必要があります。
ADB上にサンプルデータを作成
次は先ほど作成したCUSTOMER_360ユーザーが利用できる7つのサンプル表とデータの作成をします。
作成予定の表の関係は下記のようになっています。
-
データベースアクションズへログインする
先ほど新たにユーザーを作成したデータベースアクションズにてクエリを行います。前回はADMINとしてログインしましたが、今回はCUSTOMER_360としてログインします。
ログインする際のURLにはCUSTOMER_360としてログインするため、/customer_360/という文字列が含まれているはずです。
-
テーブルが既に存在する場合、ドロップする
テーブルに余計なデータが含まれていないように、もし既存のテーブルが存在する場合、下記のクエリでテーブルをドロップします。DROP TABLE account; DROP TABLE customer; DROP TABLE merchant; DROP TABLE owned_by; DROP TABLE parent_of; DROP TABLE purchased; DROP TABLE transfer;
-
ACCOUNTテーブルを作成する
CREATE TABLE account ( id NUMBER NOT NULL , account_no VARCHAR2(20) , customer_id NUMBER , open_date VARCHAR2(20) , balance NUMBER , CONSTRAINT account_pk PRIMARY KEY (id) ); INSERT INTO account VALUES (201,'xxx-yyy-201',101,'2015-10-04',1500); INSERT INTO account VALUES (202,'xxx-yyy-202',102,'2012-09-13',200); INSERT INTO account VALUES (203,'xxx-yyy-203',103,'2016-02-04',2100); INSERT INTO account VALUES (204,'xxx-yyy-204',104,'2018-01-05',100); INSERT INTO account VALUES (211,'xxx-zzz-211',NULL,NULL,NULL); INSERT INTO account VALUES (212,'xxx-zzz-212',NULL,NULL,NULL); COMMIT;
-
CUSTOMERテーブルを作成する
CREATE TABLE customer ( id NUMBER NOT NULL, name VARCHAR2(20), age NUMBER, location VARCHAR2(20), gender VARCHAR2(20), student VARCHAR2(20) , CONSTRAINT customer_pk PRIMARY KEY (id) ); INSERT INTO customer VALUES (101,'John',10,'Boston',NULL,NULL); INSERT INTO customer VALUES (102,'Mary',NULL,NULL,'F',NULL); INSERT INTO customer VALUES (103,'Jill',NULL,'Boston',NULL,NULL); INSERT INTO customer VALUES (104,'Todd',NULL,NULL,NULL,'true'); COMMIT;
-
MERCHANTテーブルを作成する
CREATE TABLE merchant ( id NUMBER NOT NULL , name VARCHAR2(20) , CONSTRAINT merchant_pk PRIMARY KEY (id) ); INSERT INTO merchant VALUES (301,'Apple Store'); INSERT INTO merchant VALUES (302,'PC Paradise'); INSERT INTO merchant VALUES (303,'Kindle Store'); INSERT INTO merchant VALUES (304,'Asia Books'); INSERT INTO merchant VALUES (305,'ABC Travel'); COMMIT;
-
PARENT_OFテーブルを作成する
CREATE TABLE parent_of ( customer_id_parent NUMBER , customer_id_child NUMBER , CONSTRAINT parent_of_pk PRIMARY KEY (customer_id_parent, customer_id_child) ); INSERT INTO parent_of VALUES (103,104); COMMIT;
-
PURCHASEDテーブルを作成する
CREATE TABLE purchased ( id NUMBER , account_id NUMBER , merchant_id NUMBER , amount NUMBER , CONSTRAINT purchased_pk PRIMARY KEY (id) ); INSERT INTO purchased VALUES (1001,201,301,800); INSERT INTO purchased VALUES (1002,201,302,15); INSERT INTO purchased VALUES (1003,202,301,150); INSERT INTO purchased VALUES (1004,202,302,20); INSERT INTO purchased VALUES (1005,202,304,10); INSERT INTO purchased VALUES (1006,203,301,350); INSERT INTO purchased VALUES (1007,203,302,20); INSERT INTO purchased VALUES (1008,203,303,15); INSERT INTO purchased VALUES (1009,204,303,10); INSERT INTO purchased VALUES (1010,204,304,15); INSERT INTO purchased VALUES (1011,204,305,450); COMMIT;
-
TRANSFERテーブルを作成する
CREATE TABLE transfer ( id NUMBER , account_id_from NUMBER , account_id_to NUMBER , amount NUMBER , transfer_date VARCHAR2(20) , CONSTRAINT transfer_pk PRIMARY KEY (id) ); INSERT INTO transfer VALUES (100001,201,202,200,'2018-10-05'); INSERT INTO transfer VALUES (100002,211,202,900,'2018-10-06'); INSERT INTO transfer VALUES (100003,202,212,850,'2018-10-06'); INSERT INTO transfer VALUES (100004,201,203,500,'2018-10-07'); INSERT INTO transfer VALUES (100005,203,204,450,'2018-10-08'); INSERT INTO transfer VALUES (100006,204,201,400,'2018-10-09'); INSERT INTO transfer VALUES (100007,202,203,100,'2018-10-10'); INSERT INTO transfer VALUES (100008,202,201,300,'2018-10-10'); COMMIT;
グラフを作成する
-
グラフサーバーにSSHでopcユーザーとして接続
鍵はサーバーを作成するときに預けた公開鍵とペアになるものを使いますssh -i <private_key> opc@<public_ip_for_compute> 例) ssh -i key.pem opc@203.0.113.14
-
グラフクライアントを利用して、グラフを作成、クエリします。
opg4py -b https://localhost:7007 -u customer_360 #接続に成功すると下記のような表示になります password: Oracle Graph Client Shell 21.4.2 >>>
-
グラフを作成する
既存のテーブルからグラフを作成するためのstatementを作成しますstatement = ''' CREATE PROPERTY GRAPH "customer_360" VERTEX TABLES ( customer , account , merchant ) EDGE TABLES ( account SOURCE KEY(id) REFERENCES account DESTINATION KEY(customer_id) REFERENCES customer LABEL owned_by PROPERTIES (id) , parent_of SOURCE KEY(customer_id_parent) REFERENCES customer DESTINATION KEY(customer_id_child) REFERENCES customer , purchased SOURCE KEY(account_id) REFERENCES account DESTINATION KEY(merchant_id) REFERENCES merchant , transfer SOURCE KEY(account_id_from) REFERENCES account DESTINATION KEY(account_id_to) REFERENCES account ) '''
-
グラフを作成するためにPGQLのDDLを実行する
Falseと表示されても正しい動きです>>> session.prepare_pgql(statement).execute() False # これは期待される結果です
新たに作成されたグラフを確認する
引き続きPythonシェルから、先ほど作成されたグラフを確認します。
-
グラフをアタッチする
graph = session.get_graph("customer_360")
-
グラフが作成されているかgraphコマンドで確認する
graph #成功していれば下記のような表示に PgxGraph(name: customer_360, v: 15, e: 24, directed: True, memory(Mb): 0)
PGQLでグラフをクエリする
作成されたグラフに対していくつかのクエリを行っていきます
-
ノードのラベル一覧を確認する
graph.query_pgql(""" SELECT DISTINCT LABEL(v) FROM MATCH (v) """).print() #成功していれば下記のような表示に +----------+ | LABEL(v) | +----------+ | ACCOUNT | | CUSTOMER | | MERCHANT | +----------+
-
それぞれのラベルに何個のノードがあるのか数える
graph.query_pgql(""" SELECT COUNT(v), LABEL(v) FROM MATCH (v) GROUP BY LABEL(v) """).print() +---------------------+ | COUNT(v) | LABEL(v) | +---------------------+ | 5 | MERCHANT | | 6 | ACCOUNT | | 4 | CUSTOMER | +---------------------+
-
エッジのラベル一覧を確認する
graph.query_pgql(""" SELECT DISTINCT LABEL(e) FROM MATCH ()-[e]->() """).print() +-----------+ | LABEL(e) | +-----------+ | OWNED_BY | | PARENT_OF | | PURCHASED | | TRANSFER | +-----------+
-
それぞれのラベルに何個のエッジがあるのか数える
graph.query_pgql(""" SELECT COUNT(e), LABEL(e) FROM MATCH ()-[e]->() GROUP BY LABEL(e) """).print() +----------------------+ | COUNT(e) | LABEL(e) | +----------------------+ | 4 | OWNED_BY | | 8 | TRANSFER | | 1 | PARENT_OF | | 11 | PURCHASED | +----------------------+
グラフを永続化させる
前のステップで作成されてたグラフは、現行セッションのみで有効なデフォルトではプライベートなグラフです。新たなセッションでもグラフを参照するためには、グラフをpublishする必要があります。
1.グラフをpublishする
※この操作にはPGX_SESSION_ADD_PUBLISHED_GRAPHロールが必要です。ロールが付与されていない場合、ADMINユーザーでデータベースのユーザーに権限を付与してから、Pythonシェルに再接続する必要があります。
graph.publish()
グラフサーバーが再起動や停止されない限り、次からは下記のコマンドでメモリ内に保存されたグラフに再読み込み不要でアクセスすることが可能になります。
graph = session.get_graph("customer_360")
まとめ
今回はセットアップから簡単なクエリまで実行してみました。次はより詳しいグラフの分析や可視化方法を実行してみましょう!