Oracle Cloud(OCI)のDBaaSでPGXを使用してグラフデータを可視化するまでの手順

##今回のゴール
Oracle Cloud(OCI)のDBaaSでPGXを使用し、グラフデータをデータベースにロードして可視化します。

##記事を書いたきっかけ

DBaaSでPGXを使用するまでに結構多くのエラーが発生してしまったので、スムーズにDBaaSでPGXを使えるようにするための手順書を記事として残しておきます。

##想定読者

- Oracle Cloudでグラフデータの可視化を簡単に試してみたい人
- グラフの世界に興味がある人

##動作環境
- Cytoscape 3.2.1 （Oracle Pluginを利用する際はCytoscape 3.2.1以上であることが条件、PCにインストール）
- [Cytoscape Plugin for Oracle Database 18c](https://www.oracle.com/database/technologies/semantic-technologies-downloads.html)
- OCI（Oracle Cloud Infrastructure）上に作成した Database - Virtual Machines
- Oracle Database 19c EE High Perf Release 18.0.0.0.0 　（プロパティ・グラフの利用にはHigh Performance以上のEditionが必要）
- Teraterm
- Windows 10 のローカルPC

##DBaaSの設定（環境構築）でお困りの方へ

[こちらの記事](https://qiita.com/feifo/items/f313df03ecf52a6fa1a0)を参照してください。Oracle Cloud(OCI)のDBaaSを使う際の、ハマりポイントが詳しく書かれています。

##DBaaSでPGXを使うための手順

DBaaSでPGXを使用する際、データベースの初期化パラメータをデフォルト値のままにすると、データベースへの接続を作成する際に以下のエラーが発生します。
###ORA-00910: specified length too long for its datatype

```groovy
[oracle@pgx groovy]$ sh gremlin-opg-rdbms.sh
--------------------------------
opg-oracledb> oracle = new Oracle("<jdbc_url", "Username", "password");
opg-oracledb> opg = OraclePropertyGraph.getInstance(oracle, "connections");
08:42:53.315 [main] ERROR oracle.pg.rdbms.OraclePropertyGraph - createGraphTables: Please enable 32K maximum length support to avoid the following error.
java.sql.SQLSyntaxErrorException: ORA-00910: specified length too long for its datatype
```
###原因
プロパティグラフがデータベースに確立された際に自動的に作成される表において、サイズ（文字数）が15000の列が存在するためです。

例えば、プロパティグラフ``myGraph``がデータベースに確立された際に作成される表は、以下の通りです。

```sql
SQL> describe myGraphVT$
 Name                       Null?    Type
 ----------------------------------------- -------- ----------------------------
 VID                       NOT NULL NUMBER
 K                                  NVARCHAR2(3100)
 T                                  NUMBER(38)
 V                                  NVARCHAR2(15000)  /*<--これ！*/
 VN                                 NUMBER
 VT                                 TIMESTAMP(6) WITH TIME ZONE
 SL                                 NUMBER
 VTS                                DATE
 VTE                                DATE
 FE                                 NVARCHAR2(4000)


SQL> describe myGraphGE$
 Name                       Null?    Type
 ----------------------------------------- -------- ----------------------------
 EID                        NOT NULL NUMBER
 SVID                       NOT NULL NUMBER
 DVID                       NOT NULL NUMBER
 EL                                  NVARCHAR2(3100)
 K                                   NVARCHAR2(3100)
 T                                   NUMBER(38)
 V                                   NVARCHAR2(15000)  /*<--これ！*/
 VN                                  NUMBER
 VT                                  TIMESTAMP(6) WITH TIME ZONE
 SL                                  NUMBER
 VTS                                 DATE
 VTE                                 DATE
 FE                                  NVARCHAR2(4000)
```

ノードおよびエッジのプロパティが、文字列・booleanおよびその他のシリアライズ可能データ型の場合に格納される**V列**のサイズが15000となっています。
各表に定義された列の詳細は、[ドキュメント](https://docs.oracle.com/cd/E82638_01/spgdg/using-property-graphs-oracle-database.html#GUID-728A5FBC-998C-4675-9C0A-31C9195B737D)を参照してください。


このため、あらかじめVARCHAR2の最大サイズを4000バイトから32767バイトに拡張する必要があります。


###解決策 ～varchar2の最大サイズを4000バイト→32767バイトに拡張する～
今回は、CDBと、それに付随するすべてのPDBのVARCHAR2、NVARCHAR2およびRAW列の最大サイズを増加する方法をご紹介します。
####▼SYSDBAとしてSQL*Plusに接続

```sql
[opc@pgx ~]$ sudo su oracle
[oracle@pgx opc]$ sqlplus /nolog
SQL*Plus: Release 18.0.0.0.0 - Production on Sat Nov 2 06:53:01 2019
Version 18.7.0.0.0
Copyright (c) 1982, 2018, Oracle.  All rights reserved.
SQL> conn / as sysdba
Connected.
```

####▼接続しているデータベースを表示
```sql
SQL> show con_name;
CON_NAME
------------------------------
CDB$ROOT
```
####▼初期化パラメータMAX_STRING_SIZE（VARCHAR2、NVARCHAR2およびRAWデータ型の最大サイズ）を確認

```sql

SQL> show parameter max_string_size;
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
max_string_size                      string      STANDARD
```
``STANDARD``は、Oracle Database 12cより前のOracle Databaseリリースの長さ制限が適用されることを意味します(たとえば、VARCHAR2およびNVARCHAR2には4000バイト、RAWには2000バイト)。
今回は、MAX_STRING_SIZEを``EXTENDED``にします。
``EXTENDED``は、Oracle Database 12cで導入された32767バイトの上限が適用されることを意味します。

####▼SPFILEでのMAX_STRING_SIZEの値を書き換える

```sql
SQL> ALTER SYSTEM SET max_string_size=extended scope=spfile;
System altered.
```
####▼CDBを停止

```sql
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
```

####▼UPGRADEモードでCDBを再起動

```sql
SQL> startup upgrade;
ORACLE instance started.
Total System Global Area 8053061448 bytes
Fixed Size                  8914760 bytes
Variable Size            1375731712 bytes
Database Buffers         6643777536 bytes
Redo Buffers               24637440 bytes
Database mounted.
Database opened.
```
####▼全てのPDBをUPGRADEモードで起動し、SQL*Plus終了

```sql
SQL> ALTER PLUGGABLE DATABASE ALL OPEN UPGRADE;
Pluggable database altered.
SQL> exit
```
####▼SYSDBAとしてCDBに接続し、utl32k.sqlスクリプト実行

```sql
[oracle@pgx admin]$ sqlplus /nolog
SQL*Plus: Release 18.0.0.0.0 - Production on Sat Nov 2 07:04:43 2019
Version 18.7.0.0.0
Copyright (c) 1982, 2018, Oracle.  All rights reserved.
SQL> conn / as sysdba
Connected.
SQL> @?/rdbms/admin/utl32k.sql
Session altered.
Session altered.
DOC>#######################################################################

・・・（中略）・・・

PL/SQL procedure successfully completed.
PL/SQL procedure successfully completed.
Commit complete.
Package altered.
Package altered.
Session altered.
```
####▼CDBを停止

```sql
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down. 
```
####▼通常モードでCDBを再起動

```sql
SQL> startup
ORACLE instance started.
Total System Global Area 8053061448 bytes
Fixed Size                  8914760 bytes
Variable Size            1375731712 bytes
Database Buffers         6643777536 bytes
Redo Buffers               24637440 bytes
Database mounted.
Database opened.
SQL> show con_name;
CON_NAME
------------------------------
CDB$ROOT
```
####▼PDBをUPGRADEモードで起動

```sql
SQL> show pdbs;
   CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
        2 PDB$SEED                       MOUNTED
        3 ORCL                           MOUNTED
SQL> alter pluggable database orcl open upgrade;
Pluggable database altered.
```

####▼PDBでutl32k.sqlスクリプト実行

```sql
SQL> alter session set container = orcl;
Session altered.
SQL> @?/rdbms/admin/utl32k.sql
Session altered.
Session altered.
DOC>#######################################################################

・・・（中略）・・・

PL/SQL procedure successfully completed.
PL/SQL procedure successfully completed.
Commit complete.
Package altered.
Package altered.
Session altered.
```

####▼PDBを停止

```sql
SQL> alter session set container = cdb$root;
Session altered.
SQL> alter pluggable database orcl close;
Pluggable database altered.
```

####▼PDBを通常モードで再起動

```sql
SQL> alter pluggable database orcl open;
Pluggable database altered.
SQL> show pdbs;
   CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
        2 PDB$SEED                       MOUNTED
        3 ORCL                           READ WRITE NO
SQL> exit
Disconnected from Oracle Database 18c EE High Perf Release 18.0.0.0.0 - Production
Version 18.7.0.0.0
```

####▼一般ユーザーを作成

```sql
CREATE USER opg_user IDENTIFIED BY oracle;
ALTER USER opg_user QUOTA UNLIMITED ON users;
GRANT connect, resource TO opg_user;
CONNECT opg_user/oracle;
```

####▼データベースへの接続を作成

```groovy
[oracle@pgx groovy]$ sh gremlin-opg-rdbms.sh
--------------------------------
opg-oracledb> oracle = new Oracle("<jdbc_url>", "<username>", "<password>");
==>oracle.pg.rdbms.Oracle@340b7ef6
```

jdbc url例(オラクルDBaaSの場合)

```shell
jdbc:oracle:thin:@<hostname>:1521/<pdb名>.<subnet名>.<VCN名>.oraclevcn.com

【補足】
<hostname>: $ORACLE_HOME/network/admin/tnsnames.oraに書かれているホスト名
<pdb名>: sql>show pdbs; で確認
<subnet名>: DBaaSが配置されているサブネットの名前

```

接続を作成できました！

####▼今回使用するデータ

サンプルとして提供されているフラットファイルを使用します。

```shell
[opc@pgx ~]$ more $PGX_HOME/../data/connections.opv
1,name,1,Barack%20Obama,,
1,role,1,political%20authority,,
1,occupation,1,44th%20president%20of%20United%20States%20of%20America,,
1,country,1,United%20States,,
1,political%20party,1,Democratic,,
1,religion,1,Christianity,,
2,name,1,Beyonce,,
2,role,1,singer%20actress,,
2,country,1,United%20States,,

・・・（中略）・・・

[opc@pgx ~]$ more $PGX_HOME/../data/connections.ope
1000,1,2,collaborates,weight,3,,1.0,
1001,1,3,collaborates,weight,3,,1.0,
1002,1,4,admires,weight,3,,1.0,
1003,1,5,admires,weight,3,,1.0,
1004,1,6,admires,weight,3,,1.0,
1005,1,7,admires,weight,3,,1.0,
1006,6,1,admires,weight,3,,1.0,
1007,6,7,collaborates,weight,3,,1.0,
1008,7,1,admires,weight,3,,1.0,
```



####▼プロパティグラフ``connections``を作成し、初期データをロード

```groovy
opg-oracledb> opg = OraclePropertyGraph.getInstance(oracle, "connections");
==>oraclepropertygraph with name connections
opg-oracledb> opg.countVertices();
==>0
opg-oracledb> opgdl = OraclePropertyGraphDataLoader.getInstance();
==>oracle.pg.rdbms.OraclePropertyGraphDataLoader@3015db78
opg-oracledb> vfile = "../../data/connections.opv";
==>../../data/connections.opv
opg-oracledb> efile = "../../data/connections.ope";
==>../../data/connections.ope
opg-oracledb> opgdl.loadData(opg, vfile, efile, 4/* DOP */, 10000/* batch size */, true/* rebuild index flag */, null/* options */);
==>null
opg-oracledb> opg.commit();
==>null
```
**データベースへの操作なので、コミットが必要です！**

##PGQL実行

データベースにグラフデータがロードされているかを確認するために、PGXシェルで先ほどロードしたデータを読み込んでみます。

####▼グラフをロードするための定義ファイルを作成

```shell:/tmp/connections.json"
{
  "db_engine":"RDBMS",
  "jdbc_url":"<jdbc_url>",
  "username":"<username>",
  "password":"<password>",
  "max_num_connections":8, #maximum number of database connections to use when reading the graph
  "error_handling":{}, #error handling configuration
  "format":"pg",  #graph format
  "name":"connections", #prefix of the table name (for edge and vertex tables)
  "vertex_props":[{"name":"name","type":"string","default":"no_name"}],
  "edge_props":[{"name":"weight","type":"integer","default":"1"}],
  "loading":{"load_edge_label":false}
}
```
####▼PGXシェル起動

```shell
[opc@pgx tmp]$ sh $PGX_HOME/bin/pgx
tput: unknown terminfo capability 'setafsd'
[WARNING] neither HADOOP_HOME nor HADOOP_CONF_DIR is set. If loading/storing from/to HDFS, Hadoop default configuration values will be used.

PGX Shell 3.2.0
PGX server version: 3.2.0
PGQL version: 1.1
type :help for available commands
variables instance, session and analyst ready to use
```

####▼PGXにデータをロード

```sql
pgx> G = session.readGraphWithProperties("/tmp/connections.json");
==> PgxGraph[name=connection3,N=78,E=164,created=1572835529342]
```

####▼エッジの重みが大きい順、リンク先ノードの名前順に5件表示
```sql
pgx> G.queryPgql("select n.name,e.weight, m.name where (n)-[e]->(m) order by e.weight desc, m.name").print(5).close();
+--------------------------------------------------------+
| n.name               | e.weight | m.name               |
+--------------------------------------------------------+
| CBS                  | 1000     | ABC                  |
| NBC                  | 1000     | ABC                  |
| Abdullah Gul         | 1000     | Abdel Fattah eL-Sisi |
| Abdel Fattah eL-Sisi | 1000     | Abdullah Gul         |
| Jack Ma              | 1000     | Alibaba              |
+--------------------------------------------------------+
==> null
```

データベースにグラフデータがロードされていることがわかりました。


##Cytoscapeでグラフデータを可視化
**注意！）グラフデータの可視化には、Cytoscape Pluginが必要です。インストール手順は、[こちら](https://qiita.com/y_imaaa/items/046316a3ae7b7a6c017b)を参照してください。**

####▼PGXをサーバーモードで起動

```shell
[opc@pgx bin]$ sh start-server
Nov 03, 2019 6:32:17 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-nio-7007"]

・・・（中略）・・・

INFO: Starting ProtocolHandler ["http-nio-7007"]
```

####▼[Load}→[Property graph]→[Connect to Oracle Database]

![無題Cytoscape.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/0fc8d49c-c20a-60d5-27ed-38efcd8e8c61.png)

####▼jdbc接続
![無題Cytoscape.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/aa30c874-2aac-6290-a2f2-07a6420fda24.png)

以下の3つを入力すると、作成したグラフ（connections）が選択できるようになります。

- JDBC url : ``<DBaaSのPublic IPアドレス>:<ポート番号(デフォルトは1521)/サービス名``
- Username : ``データベースのユーザー名``
- Password : ``ユーザーのパスワード``

####▼グラフデータを可視化

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/c9a1c2db-4ed6-2c82-53ec-dad7b94c09ca.png)

可視化することができました！


##まとめ

上記の手順を再度簡単にまとめると、以下のようになります。
　

###### 1. PDBのMAX_STRING_SIZEを拡張
###### 2. PDBにユーザーを作成
###### 3. データベースにデータをロード
###### 4. Cytoscapeでグラフデータを可視化
　

OCI上のDBaaSでPGXを使用する際は、varchar2の最大サイズを4000バイト→32767バイトに拡張する必要がありました。

今回ご紹介した手順は、Oracle Cloud上でDBaaSを使用することで、簡単に試すことができます。

ぜひともこの機会に、Oracle Cloudを試してみてください！

>New Always Free Services
https://www.oracle.com/cloud/free/

>［速報］Oracle Cloudを期限なく無料で使える「Always Free」発表。1GBのVM2つ、Autonomous Database 2つなど提供。Oracle OpenWorld 2019
https://www.publickey1.jp/blog/19/oracle_cloudalways_free1gbvm2autonomous_database_2oracle_openworld_2019.html

> Oracle Cloudを期限なく無料で使える「Always Free」発表　1GBのVM2つ、Autonomous DB2つなど提供
https://www.itmedia.co.jp/news/articles/1909/17/news076.html

##参考資料

>OCIマニュアル
https://docs.cloud.oracle.com/iaas/Content/Database/Tasks/connectingDB.htm?Highlight=ORACLE_SID
MAX_STRING_SIZE
https://docs.oracle.com/cd/E82638_01/refrn/MAX_STRING_SIZE.html#GUID-D424D23B-0933-425F-BC69-9C0E6724693C
PGX(3.2.0)ドキュメント
https://docs.oracle.com/cd/E56133_01/3.2.0/reference/config/pgx.html