6 インメモリー・アナリスト(PGX)の使用
Oracle Spatial and Graphのインメモリー・アナリスト機能は、一連の分析機能をサポートしています。
この章では、インメモリー・アナリストを使用する例について説明します(プロパティ・グラフ・インメモリー分析とも呼ばれ、Javadoc、コマンドライン、パスの説明、エラー・メッセージなどではPGXと省略されます)。主なトピックは次のとおりです。
- グラフのメモリーへの読込み
このトピックでは、シェル・インタフェースを使用したメモリーへの対話によるグラフの読込みの例について説明します。 - インメモリー・アナリストの構成
起動時にインメモリー・アナリストに単一のJSONファイルを割り当てることにより、インメモリー・アナリスト・エンジンおよびそのランタイム動作を構成できます。 - カスタム・グラフ・データの読取り
ユーザー独自のカスタム・グラフ・データを読み取ることができます。この例では、グラフを作成し、それを変更して正しく読み取る方法を表示します。 - グラフ・データのディスクへの格納
グラフはJavaまたはシェルを使用してメモリーに読み込んだ後、別の形式でディスクに格納できます。格納したグラフ・データは、後でインメモリー・アナリストへの入力として使用できます。 - 組込みアルゴリズムの実行
インメモリー・アナリストには、一連の組込みアルゴリズムが含まれており、Java APIとして使用できます。 - サブグラフの作成
メモリーにロードされたグラフに基づいてサブグラフを作成できます。 - グラフを使用したパターンマッチング問合せの使用
インメモリー・グラフに対してパターンマッチング問合せを発行してから、その問合せの結果を操作できます。 - インメモリー・アナリスト・サーバーの起動
Big Data Spatial and Graphには、スクリプトの実行によってインメモリー・アナリスト・サーバーを起動できるApache Tomcatの事前構成済バージョンがバンドルされています。 - Jettyへのデプロイ
インメモリー・アナリストは、Eclipse Jetty、Apache Tomcat、またはOracle WebLogic Serverにデプロイできます。この例では、Webアプリケーションとしてインメモリー・アナリストをEclipse Jettyにデプロイする方法を示しています。 - Apache Tomcatへのデプロイ
インメモリー・アナリストは、Eclipse Jetty、Apache Tomcat、またはOracle WebLogicにデプロイできます。この例では、Webアプリケーションとしてインメモリー・アナリストをApache Tomcatにデプロイする方法を示しています。 - Oracle WebLogic Serverへのデプロイ
インメモリー・アナリストは、Eclipse Jetty、Apache Tomcat、またはOracle WebLogic Serverにデプロイできます。この例では、Webアプリケーションとしてインメモリー・アナリストをOracle WebLogic Serverにデプロイする方法を示しています。 - インメモリー・アナリスト・サーバーへの接続
プロパティ・グラフのインメモリー・アナリストがサーバーとしてデプロイされ、Hadoopクラスタ(またはEclipse Jetty、Apache Tomcat、Oracle WebLogic上のWebアプリケーションとしてHadoopのないクライアント・システム)にインストールされた後、インメモリー・アナリスト・サーバーに接続できます。 - 分散モードのインメモリー・アナリストの使用
インメモリー・アナリストは、共有メモリー・モードまたは分散モードで実行できます。 - HDFSでのデータの読取りおよび格納
インメモリー・アナリストは、Hadoop Distributed File System (HDFS)をサポートしています。この例では、インメモリー・アナリストAPIを使用してHDFSのグラフ・データを読み取り、アクセスする方法を示しています。 - YARNアプリケーションとしてのインメモリー・アナリストの実行
この例では、Hadoop NextGen MapReduce (YARN)スケジューリングにより、Hadoopクラスタ上でインメモリー・アナリスト・サーバーを開始、停止および監視する方法について説明します。 - Oracleの2つの表関係形式の使用
リレーショナル・データ・モデルを使用する場合、グラフ・データは2つのリレーショナル表を使用して表現できます。1つの表はノードとそのプロパティ用で、もう1つの表はエッジとそのプロパティ用です。 - インメモリー・アナリストを使用したApache Spark内のグラフ・データの分析
Oracle Big Data Spatial and Graphのプロパティ・グラフ機能を使用すると、インメモリー分析とApache Sparkを統合できます。 - インメモリー・アナリストZeppelinインタプリタの使用
インメモリー・アナリストには、Apache Zeppelinのインタプリタ実装が用意されています。このチュートリアルのトピックでは、ローカルのZeppelinインストールにインメモリー・アナリスト・インタプリタをインストールし、いくつかの簡単な操作を実行する方法について説明します。 - インメモリー・アナリスト・エンタープライズ・スケジューラの使用
インメモリー・アナリスト・エンタープライズ・スケジューラには、高度なスケジューリング機能が用意されています。
6.1 グラフのメモリーへの読込み
このトピックでは、シェル・インタフェースを使用したメモリーへの対話によるグラフの読込みの例について説明します。
主な手順は次のとおりです。
親トピック: インメモリー・アナリスト(PGX)の使用
6.1.1 インメモリー・アナリスト・サーバー・インスタンスへの接続
インメモリー・アナリストを起動する手順:
インメモリー・アナリスト・ソフトウェアが正しくインストールされている場合、エンジン実行ログ・メッセージとインメモリー・アナリスト・シェル・プロンプト(pgx>
)が表示されます。
変数instance
、session
、およびanalyst
が使用可能です。
このトピックの前の例では、pgx
コマンドでリモートURLを指定していないため、シェルがローカル・インスタンスを開始します。
親トピック: グラフのメモリーへの読込み
6.1.3 構成ファイルでのグラフ・メタデータの指定
/opt/oracle/oracle-spatial-graph/property_graph/examples/pgx/graphs/
のインストール・ディレクトリにグラフの例が含まれています。ここでは、インメモリー・アナリストがグラフを読み取る方法を説明する構成ファイルを使用します。
pgx> cat /opt/oracle/oracle-spatial-graph/property_graph/examples/pgx/graphs/sample.adj.json
===> {
"uri": "sample.adj",
"format": "adj_list",
"node_props": [{
"name": "prop",
"type": "integer"
}],
"edge_props": [{
"name": "cost",
"type": "double"
}],
"separator": " "
}
uri
フィールドには、グラフ・データの場所を指定します。このパスは構成ファイルの親ディレクトリに対して相対的に解決します。インメモリー・アナリストがグラフをロードするとき、sample.adj
という名のファイルのexamples/graphs
ディレクトリが検索されます。
その他のフィールドは、グラフ・データが隣接するリスト形式で提供され、integer
型のノード・プロパティとdouble
型のエッジ・プロパティで構成されていることを示します。
これは隣接するリスト形式のグラフ・データです。
pgx> cat /opt/oracle/oracle-spatial-graph/property_graph/examples/pgx/graphs/sample.adj
===> 128 10 1908 27.03 99 8.51
99 2 333 338.0
1908 889
333 6 128 51.09
図6-1は、データから作成されたプロパティ・グラフを示します。
親トピック: グラフのメモリーへの読込み
6.1.4 グラフ・データのメモリーへの読込み
グラフをメモリーに読み込むには、次の情報を渡す必要があります。
-
グラフのメタデータを指定するグラフ構成ファイルへのパス
-
グラフへの参照に使用できる一意の英数字名
同じ名前で別のグラフをすでにロードしている場合は、エラーが発生します。
ファイルへのパスを指定する手順:
-
頂点およびエッジが1つのファイルに指定されている場合、
uri
を使用します。{ "uri": "path/to/file.format", ...}
-
複数のファイル(ADJ_LIST、EDGE_LISTなど)を指定するには、
uris
を使用します。{ "uris": ["file1.format", "file2.format"] ...}
ほとんどのプレーン・テキスト形式は、3つのインメモリー・アナリストによって並列で解析できます。
-
頂点またはエッジ(FLAT_FILE、TWO_TABLESなど)が含まれるかどうかに応じてファイル形式が異なる場合は、
vertex_uris
およびedge_uris
を使用します。{ "vertex_uris": ["vertices1.format", "vertices2.format"], "edge_uris": ["edges1.format", "edges2.format"] ...}
サポートされているファイル・システム
インメモリー・アナリストは、様々なプロトコルおよび仮想ファイル・システムを介したグラフ構成ファイルおよびグラフ・データ・ファイルからのロードをサポートしています。ファイル・システムまたはプロトコルのタイプは、Uniform Resource Identifier (URI)のスキームによって決まります。
-
ローカル・ファイル・システム(
file:
)。特定のURIにスキームが含まれていない場合、これがデフォルトにもなります。 -
クラスパス(
classpath:
またはres:
) -
HDFS (
hdfs:
) -
HTTP (
http:
またはhttps:
) -
様々なアーカイブ形式(
zip:
、jar:
、tar:
、tgz:
、tbz2:
、gz:
およびbz2:
)URI形式は、
scheme://arch-file-uri[!absolute-path]
です。例:jar:../lib/classes.jar!/META-INF/graph.json
パスはネストしている場合があります。例:
tar:gz:http://anyhost/dir/mytar.tar.gz!/mytar.tar!/path/in/tar/graph.data
感嘆符(!)をリテラルのファイル名文字として使用するには、
%21;
を使用してエスケープする必要があります
相対パスは常に、構成ファイルの親ディレクトリに対して相対的に解決されます。
例: シェルを使用したグラフの読取り
pgx> graph = session.readGraphWithProperties("/opt/oracle/oracle-spatial-graph/property_graph/examples/pgx/graphs/sample.adj.json", "sample"); ==> PgxGraph[name=sample,N=4,E=4,created=1476225669037] pgx> graph.getNumVertices() ==> 4
例: Javaを使用したグラフの読取り
import oracle.pgx.api.*; ServerInstance instance = Pgx.getInstance(Pgx.EMBEDDED_URL); // ServerInstance instance = Pgx.getInstance("http://my-server:7007"); // remote instance PgxSession session = instance.createSession("my-session"); PgxGraph graph = session.readGraphWithProperties("/opt/oracle/oracle-spatial-graph/property_graph/examples/pgx/graphs/sample.adj.json");
例: JavaScriptを使用したグラフの読取り
const pgx = require('oracle-pgx-client'); let p = pgx.connect("http://my-server:7007"); let json = { "uri": "sample.adj", "format": "adj_list", "node_props": [{ "name": "prop", "type": "integer" }], "edge_props": [{ "name": "cost", "type": "double" }], "separator": " " } p.then(function(session) { return session.readGraphWithProperties(json); }).then(function(graph) { // do something with graph });
次のトピックでは、プロパティ・グラフをメモリーに読み込むその他の例について説明します。
- Apache HBaseに格納されているグラフのメモリーへの読込み
- Oracle NoSQL Databaseに格納されているグラフのメモリーへの読込み
- ローカル・ファイル・システムに格納されているグラフのメモリーへの読込み
親トピック: グラフのメモリーへの読込み
6.1.4.1 Apache HBaseに格納されているグラフのメモリーへの読込み
Apache HBaseに格納されているプロパティ・グラフを読み取るには、次のようにJSONベースの構成ファイルを作成できます。定数、クライアント・ポート、グラフ名、およびその他の情報は、ユーザーの設定に応じてカスタマイズする必要があります。
% cat /tmp/my_graph_hbase.json { "format": "pg", "db_engine": "hbase", "zk_quorum": "scaj31bda07,scaj31bda08,scaj31bda09", "zk_client_port": 2181, "name": "connections", "node_props": [{ "name": "country", "type": "string" }], "edge_props": [{ "name": "label", "type": "string" }, { "name": "weight", "type": "float" }], "loading": { "load_edge_label": true } } EOF
次のコマンドを使用すると、プロパティ・グラフconnections
がメモリーに読み込まれます。
pgx> session.readGraphWithProperties("/tmp/my_graph_hbase.json", "connections") ==> PGX Graph named connections ...
大きいサイズのグラフを扱う場合は、IOワーカー、分析対象のワーカー数、タスクのタイムアウトなどのパラメータを調整する必要があります。「インメモリー・アナリストの構成」を参照してください。
親トピック: グラフ・データのメモリーへの読込み
6.1.4.2 Oracle NoSQL Databaseに格納されているグラフのメモリーへの読込み
Oracle NoSQL Databaseに格納されているプロパティ・グラフを読み取るには、次のようにJSONベースの構成ファイルを作成できます。ホスト、ストア名、グラフ名、およびその他の情報は、ユーザーの設定に応じてカスタマイズする必要があります。
% cat /tmp/my_graph_nosql.json { "format": "pg", "db_engine": "nosql", "hosts": [ "zathras01:5000" ], "store_name": "kvstore", "name": "connections", "node_props": [{ "name": "country", "type": "string" }], "loading": { "load_edge_label": true }, "edge_props": [{ "name": "label", "type": "string" }, { "name": "weight", "type": "float" }] }
次に、構成ファイルをメモリーに読み込みます。次の例では、スニペットがファイルをメモリーに読み込み、方向のないグラフ(名称U
)を元のデータから生成し、三角形の数をカウントします。
pgx> g = session.readGraphWithProperties("/tmp/my_graph_nosql.json", "connections") pgx> analyst.countTriangles(g, false) ==> 8
親トピック: グラフ・データのメモリーへの読込み
6.1.4.3 ローカル・ファイル・システムに格納されているグラフのメモリーへの読込み
次のコマンドでは、「構成ファイルでのグラフ・メタデータの指定」の構成ファイルおよびmy-graph
という名前を使用します。
pgx> g = session.readGraphWithProperties("/opt/oracle/oracle-spatial-graph/property_graph/examples/pgx/graphs/sample.adj.json", "my-graph")
親トピック: グラフ・データのメモリーへの読込み
6.2 インメモリー・アナリストの構成
起動時にインメモリー・アナリストに単一のJSONファイルを割り当てることにより、インメモリー・アナリスト・エンジンおよびそのランタイム動作を構成できます。
このファイルには、次の表に示すパラメータを含めることができます。一部の例はこの表に従います。
構成ファイルを指定するには、「インメモリー・アナリストの構成ファイルの指定」を参照してください。
注意:
-
パラメータ値の相対パスは常に、指定先の構成ファイルに対して相対的に解決されます。たとえば、構成ファイルが
/pgx/conf/pgx.conf
であり、パラメータ値内のファイルがgraph-configs/my-graph.bin.json
として指定されている場合、ファイル・パスは/pgx/conf/graph-configs/my-graph.bin.json
に解決されます。 -
パラメータのデフォルト値は、一連の広範なアルゴリズム全体にわたって最善のパフォーマンスを実現できるよう最適化されます。ワークロードに応じて、様々な戦略、サイズおよびしきい値を使用して試験することにより、パフォーマンスをさらに改善できる場合があります。
表6-1 インメモリー・アナリストの構成パラメータ
パラメータ | 型 | 説明 | デフォルト |
---|---|---|---|
admin_request_cache_timeout |
integer |
管理要求結果がキャッシュから削除されるまでの秒数。実行されていないかまだ使用されていない要求は、このタイムアウトから除外されます。注意: これが関連するのは、PGXがWebアプリケーションとしてデプロイされている場合のみです。 |
60 |
allow_idle_timeout_overwrite |
boolean |
trueの場合、セッションによってデフォルトのアイドル・タイムアウトを上書きできます。 |
true |
allow_local_filesystem |
boolean |
(このフラグを使用すると、セキュリティが弱体化するため、作業の影響を把握している場合のみ使用してください。)クライアント/サーバー・モードである場合、ローカル・ファイル・システムからのロードを可能にします。警告: これを有効にするのは、PGXリモート・インタフェースのユーザーがローカル・ファイル・システム上のファイルにアクセスするのを明示的に許可する場合のみにする必要があります。 |
false |
allow_task_timeout_overwrite |
boolean |
trueの場合、セッションによってデフォルトのタスク・タイムアウトを上書きできます |
true |
allow_user_auto_refresh |
boolean |
trueの場合、ユーザーがロードするグラフを自動リフレッシュできます。falseの場合、graphsに記述されているグラフのみに対して自動リフレッシュを有効にできます。 |
false |
bfs_iterate_que_task_size |
integer |
BFS反復QUEフェーズのタスク・サイズ。 |
128 |
bfs_threshold_read_based |
integer |
BFSトラバース・レベル・アイテムを読取りベースのアクセス戦略に切り替える際のしきい値。 |
1024 |
bfs_threshold_single_threaded |
integer |
BFSトラバース・レベル・アイテムの頂点が単一スレッドでアクセスされる数のしきい値。 |
128 |
cctrace |
boolean |
trueの場合、すべての呼出しを制御またはコア・インタフェースに記録します。 |
false |
cctrace_out |
string |
[cctraceに関連]cctraceが有効である場合、cctraceの記録先のファイルへのパスを指定します。nullの場合、stderrに記録されます。特別な値:log:である場合、デフォルトのPGXロギング・ファシリティが使用されます |
null |
character_set |
string |
PGX全体にわたって使用する標準文字セット。UTF-8がデフォルトです。注意: 一部の機能には互換性がない場合があります。 |
utf-8 |
cni_diff_factor_default |
integer |
一般的な近傍イテレータ実装で使用されるデフォルトの差異係数値。 |
8 |
cni_small_default |
integer |
一般的な近傍イテレータ実装で使用されるデフォルト値で、このしきい値を下回ると、部分配列が小さいと見なされることを示します。 |
128 |
cni_stop_recursion_default |
integer |
一般的な近傍イテレータ実装で使用されるデフォルト値で、バイナリ検索アプローチが適用される最小サイズを示します。 |
96 |
dfs_threshold_large |
integer |
DFS実装が多数の頂点に対して最適化されたデータ構造に切り替わるまでにどれくらいの数の頂点がアクセスされる必要があるかを決める値。 |
4096 |
enable_csrf_token_checks |
boolean |
trueの場合、PGX Webアプリケーションは、クライアントから送信された要求パラメータとクロスサイト・リクエスト・フォージェリ(CSRF)トークンCookieが存在して一致するかどうかを検証します。これは、CSRF攻撃を防止することが目的です。 |
true |
enable_solaris_studio_labeling |
boolean |
[solaris studioを使用してプロファイリングする場合に関連]有効である場合、'er_label'コマンドを使用して試験にラベルが付けられます。 |
false |
explicit_spin_locks |
boolean |
trueは、ロックが使用可能になるまでループ内で明示的にスピンすることを意味します。falseは、コンテキストを切り替えるかスピンするかを決定するためにJVMに依存するJDKロック・キーを使用することを意味します。通常、この値をtrueに設定した方がパフォーマンスが向上します。 |
true |
graphs |
stringの配列 |
起動時に登録するグラフ構成へのパスのリスト。 |
[] |
max_active_sessions |
integer |
一度に有効することが許可されたセッションの最大数。 |
1024 |
max_off_heap_size |
integer |
OutOfMemoryErrorがスローされるまでにPGXが割り当てることが許可されたオフピーク・メモリーの最大量(メガバイト単位)。注意: この制限は、丸めおよび同期のトレードオフのため、絶対に超えないことが保証されるわけではありません。これは、PGXが新しいメモリー割当て要求を拒否し始めた際のしきい値としてのみ機能します。 |
<使用可能な物理メモリー> |
max_queue_size_per_session |
integer |
セッションごとにキューに入れておくことが許可された保留タスクの最大数。セッションが最大に達すると、新しく受け取ったそのセッションの要求が拒否されます。マイナスの値は、制限がないことを意味します。 |
-1 |
max_snapshot_count |
integer |
同時にエンジンにロードすることが可能なスナップショットの数。新しいスナップショットは、自動更新または強制更新を介して作成できます。グラフのスナップショットの数がこのしきい値に達した場合、これ以上の自動更新は実行されなくなり、1つ以上のスナップショットがメモリーから削除されるまでは、強制更新を実行すると例外が発生します。値がゼロの場合、無制限の数のスナップショットをサポートすることを示します。 |
0 |
memory_cleanup_interval |
integer |
メモリーのクリーンアップ間隔(秒単位)。 |
600 |
ms_bfs_frontier_type_strategy |
enum[auto_grow, short, int] |
MS-BFSフロンティアに使用するタイプの戦略。 |
auto_grow |
num_spin_locks |
integer |
生成された各アプリケーションがインストールを作成するスピン・ロックの数。トレードオフ: 数が小さい場合、メモリーの消費量が小さいことを意味し、数が大きい場合、実行処理が速くなることを意味します(アルゴリズムにスピン・ロックが使用されている場合)。 |
1024 |
num_workers_analysis |
integer |
分析タスクに使用するワーカー・スレッドの数。 |
<no-of-cpus> |
num_workers_fast_track_analysis |
integer |
高速分析タスクに使用するワーカー・スレッドの数。 |
1 |
num_workers_io |
integer |
I/Oタスク(ロード/リフレッシュ/ディスクへの/からの読込み)タスクに使用するワーカー・スレッドの数。ファイルベースのローダーは常に単一スレッドであるため、この値はこれらには影響しません。データベース・ローダーは、I/Oワーカーごとに新しい接続を開きます。 |
<no-of-cpus> |
pattern_matching_semantic |
enum[isomorphism, homomorphism] |
グラフ・パターン一致セマンティックで、homomorphismまたはisomorphismのどちらかです。 |
homomorphism |
parallelization_strategy |
enum[segmented, task_stealing, task_stealing_counted, rts] |
使用するパラレル化戦略:segmented = ワークをセグメントに分割し、セグメントごとに1つのスレッドを使用します。task_stealing = 再帰アクションを使用したF/Jプール。task_stealing_counted = 結合を削減するためにカウントされたコンプリータを使用したF/Jプール。 rts = 試験的ランタイム・システム。 |
task_stealing_counted |
random_generator_strategy |
enum[non_deterministic, deterministic] |
インメモリー・アナリストでランダム数を生成するためのメソッド。 |
non_deterministic |
random_seed |
long |
[deterministicランダム数ジェネレータのみに関連]インメモリー・アナリストで使用されるdeterministicランダム数ジェネレータのシード。デフォルトは-24466691093057031です。 |
-24466691093057031 |
release_memory_threshold |
number |
エンジンが未使用のグラフを解放するまでの使用済メモリーのしきい値パーセンテージ(小数)。例: 値が0.0である場合、グラフは参照数がゼロになると同時に解放されることを意味します。つまり、そのグラフをロードしたすべてのセッションが破棄されます/タイムアウトします。値が1.0である場合、グラフは一切解放されず、メモリーに収まらないグラフが必要になると同時にOutOfMemoryErrorsがスローされます。値が0.7である場合、メモリー内のグラフを現在使用しているセッションがない場合でも、メモリー消費量の合計が使用可能なメモリー合計の70%を下回っている限り、これらのグラフがすべて保持されます。消費量が70%を超えているときに別のグラフをロードする必要がある場合、メモリー消費量が再度70%を下回るまで未使用のグラフが解放されます。 |
0.85 |
session_idle_timeout_secs |
integer |
アイドル中のセッションのタイムアウト(秒単位)。ゼロ(0)は、タイムアウトが行われないことを意味します。 |
0 |
session_task_timeout_secs |
integer |
セッション(アルゴリズム、I/Oタスク)によって発行された長時間のタスクを中断までのタイムアウト(秒単位)。ゼロ(0)は、タイムアウトが行われないことを意味します。 |
0 |
small_task_length |
integer |
ワークの合計量がデフォルトのタスクの長さより小さい場合のタスクの長さ(タスク・スティーリング戦略の場合のみ関連)。 |
128 |
spark_streams_interface |
string |
Sparkデータ通信にはインタフェースの名前が使用されます。 |
null |
strict_mode |
boolean |
trueの場合、無効なキー、不一致、および他の潜在的なエラーなどの構成問題が発生した場合は常に例外がスローされ、ERRORレベルで記録されます。falseの場合、(重大度に応じて)問題がERROR/WARNレベルで記録され、推測が行われ、例外をスローする代わりに合理的なデフォルトが使用されます。 |
true |
task_length |
integer |
デフォルトのタスクの長さ(タスク・スティーリング戦略の場合のみ関連)。100から10000にする必要があります。トレードオフ: 数が小さい場合、よりファイングレインなタスクが生成され、スティーリングのスループットが高くなります。数が大きい場合、メモリー消費量およびGCアクティビティが小さくなります。 |
4096 |
tmp_dir |
string |
コンパイル・アーティファクトおよび他の一時データを格納するための一時ディレクトリ。<system-tmp-dir>に設定されている場合、基礎となるシステムの標準tmpディレクトリ(Linuxの場合は/tmp)を使用します。 |
<system-tmp-dir> |
use_string_pool |
boolean |
trueの場合、インメモリー・アナリストは、文字列プロパティに対するメモリーの消費を削減するためにプール内に文字列プロパティを格納します。 |
true |
例6-1 最小限のインメモリー・アナリスト構成
次の例を使用すると、インメモリー・アナリストにより、32のワーカーが含まれる分析スレッド・プールが初期化されます。(他のすべてのパラメータにデフォルト値が使用されます。)
{ "num_workers_analysis": 32 }
例6-2 2つの固定グラフを使用したインメモリー・アナリスト構成
次の例では、インメモリー・アナリストの起動時に2つの固定グラフをメモリーロードするためのgraphs
パラメータを含む、追加パラメータを指定します。この機能を使用すると、同じグラフ構成を事前にロードし、後でグラフを参照するためにスタンドアロンで使用する必要がある場合に冗長性が生じないようにすることができます。
{
"num_workers_analysis": 32,
"num_workers_fast_track_analysis": 32,
"memory_cleanup_interval": 600,
"max_active_sessions": 1,
"release_memory_threshold": 0.2,
"graphs": ["graph-configs/my-graph.bin.json", "graph-configs/my-other-graph.adj.json"]
}
例6-3 デフォルト以外のランタイム値を使用したインメモリー・アナリスト構成
次の例では、インメモリー・アナリストのランタイム動作を構成するためにいくつかのパラメータを指定します。
{ "num_workers_analysis": 32, "num_spin_locks": 128, "task_length": 1024, "array_factory_strategy": "java_arrays" }
6.2.1 インメモリー・アナリストの構成ファイルの指定
インメモリー・アナリストの構成ファイルは、ServerInstance#startEngine
(または任意のバリアント)が呼び出されるたびに起動時にインメモリー・アナリストによって解析されます。構成ファイルへのパスをインメモリー・アナリストに書き込むことも、プログラム的に指定することもできます。このトピックでは、ファイルを指定する複数の方法を識別します
プログラム的
すべての構成フィールドがJava列挙型として存在します。例:
Map<PgxConfig.Field, Object> pgxCfg = new HashMap<>(); pgxCfg.put(PgxConfig.Field.NUM_WORKERS_ANALYSIS, 32); ServerInstance instance = ... instance.startEngine(pgxCfg);
明示的に設定されていないすべてのパラメータにデフォルト値が使用されます。
ファイルの明示的な使用
地図の代わりに、インメモリー・アナリスト構成JSONファイルへのパスを書き込むことができます。例:
instance.startEngine("path/to/pgx.conf"); // file on local file system instance.startEngine("hdfs:/path/to/pgx.conf"); // file on HDFS (required $HADOOP_CONF_DIR on the classpath) instance.startEngine("classpath:/path/to/pgx.conf"); // file on current classpath
他のすべてのプロトコルの場合、JSONファイルへの入力ストリームに直接書き込むことができます。例:
InputStream is = ... instance.startEngine(is);
ファイルの暗黙的な使用
startEngine()
が引数なしで呼び出されると、インメモリー・アナリストは、次の場所にある構成ファイルを探し、ファイルが見つかったら停止します。
-
Javaシステム・プロパティ
pgx_conf
内にあるファイル・パス。例:java -Dpgx_conf=conf/my.pgx.config.json ...
-
現在のクラスパスのルート・ディレクトリ内の
pgx.conf
という名前のファイル -
現在の
System.getProperty("user.dir")
ディレクトリに対して相対的なルート・ディレクトリ内のpgx.conf
という名前のファイル
注意: 構成を用意するかどうかは任意です。特定の構成ファイル内でフィールドが見つからない場合、または構成ファイルが用意されていない場合、各フィールドのデフォルト値が使用されます。
ローカル・シェルの使用
シェルによるローカルのインメモリー・アナリスト・インスタンスの構成方法を変更するには、$PGX_HOME/conf/pgx.conf
を編集します。変更は、$PGX_HOME/bin/pgx
を次回呼び出すときに反映されます。
次の例のように構成ファイルの場所を変更することもできます。
./bin/pgx --pgx_conf path/to/my/other/pgx.conf
システム・プロパティの設定
インメモリー・アナリストが実行されているJVMに-Dpgx.<FIELD>=<VALUE>
引数を書き込むことにより、Javaシステム・プロパティを使用して任意のパラメータを設定できます。システム・プロパティを設定すると、他の任意の構成が上書きされます。次の例では、他の任意の構成がどのように設定されているかとは関係なく、最大オフピーク・サイズを256GBに設定します。
java -Dpgx.max_off_heap_size=256000 ...
環境変数の設定
インメモリー・アナリストが実行されているJVMの環境変数に'PGX_'を追加することにより、環境変数を使用して任意のパラメータを設定することもできます。環境変数を設定すると、他の任意の構成が上書きされます。ただし、システム・プロパティおよび環境変数が同じパラメータに設定されている場合、システム・パラメータ値が使用されます。次の例では、環境変数を使用して最大オフヒープ・サイズを256GBに設定します。
PGX_MAX_OFF_HEAP_SIZE=256000 java ...
親トピック: インメモリー・アナリストの構成
6.3 カスタム・グラフ・データの読取り
ユーザー独自のカスタム・グラフ・データを読み取ることができます。この例では、グラフを作成し、それを変更して正しく読み取る方法を表示します。
このグラフでは隣接するリスト形式を使用しますが、インメモリー・アナリストでは、複数のグラフ形式をサポートしています。
主な手順は次のとおりです。
6.3.1 単純なグラフ・ファイルの作成
この例では、頂点またはエッジ・プロパティのない、単純な小さいグラフを隣接するリストに作成します。それぞれの線には、頂点(ノード) ID、およびその出力エッジ点が指し示す頂点IDが含まれます。
1 2 2 3 4 3 4 4 2
このリストでは、単一スペースで個々のトークンを区切ります。インメモリー・アナリストではその他のセパレータもサポートしており、グラフ構成ファイルで指定できます。
図6-2は、4つの頂点と5つのエッジのあるプロパティ・グラフとしてレンダリングされたデータを示します。(頂点2および頂点4の間には2つのエッジがあり、各エッジは互いの反対の方向を指し示しています。)
インメモリー・アナリストへのグラフの読込みには、グラフ構成が必要です。グラフ構成は、次のいずれかのメソッドを使用して指定できます。
-
JSON形式での構成設定のファイルへの書込み
-
Java
GraphConfigBuilder
オブジェクトの使用。
次の例では、両方のメソッドを示します。
JSON構成
{ "uri": "graph.adj", "format":"adj_list", "separator":" " }
Java構成
import oracle.pgx.config.FileGraphConfig; import oracle.pgx.config.Format; import oracle.pgx.config.GraphConfigBuilder; FileGraphConfig config = GraphConfigBuilder .forFileFormat(Format.ADJ_LIST) .setUri("graph.adj") .setSeparator(" ") .build();
親トピック: カスタム・グラフ・データの読取り
6.3.2 頂点プロパティの追加
「単純なグラフ・ファイルの作成」のグラフは、頂点プロパティまたはエッジ・プロパティを使用しない頂点とエッジで構成されています。頂点プロパティは、それぞれの線の元の頂点IDに続いて配置されます。double
頂点(ノード)プロパティを値0.1、2.0、0.3および4.56789とともにグラフに追加すると、グラフ・データは次のようになります。
1 0.1 2 2 2.0 3 4 3 0.3 4 4 4.56789 2
注意:
インメモリー・アナリストは同種のグラフのみをサポートしており、すべての頂点のプロパティの数とタイプは同じです。
インメモリー・アナリストで、変更したデータ・ファイルを読み取るには、構成ファイルまたはビルダー・コードで頂点(ノード)プロパティを追加する必要があります。次の例では、プロパティを説明する名前を入力し、タイプをdouble
に設定します。
JSON構成
{ "uri": "graph.adj", "format":"adj_list", "separator":" ", "node_props":[{ "name":"double-prop", "type":"double" }] }
Java構成
import oracle.pgx.common.types.PropertyType; import oracle.pgx.config.FileGraphConfig; import oracle.pgx.config.Format; import oracle.pgx.config.GraphConfigBuilder; FileGraphConfig config = GraphConfigBuilder.forFileFormat(Format.ADJ_LIST) .setUri("graph.adj") .setSeparator(" ") .addNodeProperty("double-prop", PropertyType.DOUBLE) .build();
親トピック: カスタム・グラフ・データの読取り
6.3.3 頂点識別子としての文字列の使用
前の例では、integer
頂点(ノード) IDを使用しています。インメモリー分析のデフォルトはinteger
頂点IDですが、string
頂点IDを使用するようにグラフを定義することもできます。
このデータ・ファイルには桁数だけではなく、"node 1"、"node 2"などを使用できます。
"node 1" 0.1 "node 2" "node 2" 2.0 "node 3" "node 4" "node 3" 0.3 "node 4" "node 4" 4.56789 "node 2"
ここでも、データ・ファイルと一致するようにグラフ構成を変更する必要があります。
JSON構成
{ "uri": "graph.adj", "format":"adj_list", "separator":" ", "node_props":[{ "name":"double-prop", "type":"double" }], "node_id_type":"string" }
Java構成
import oracle.pgx.common.types.IdType; import oracle.pgx.common.types.PropertyType; import oracle.pgx.config.FileGraphConfig; import oracle.pgx.config.Format; import oracle.pgx.config.GraphConfigBuilder; FileGraphConfig config = GraphConfigBuilder.forFileFormat(Format.ADJ_LIST) .setUri("graph.adj") .setSeparator(" ") .addNodeProperty("double-prop", PropertyType.DOUBLE) .setNodeIdType(IdType.STRING) .build();
注意:
string
頂点IDは、integer
頂点IDより多くのメモリーを消費します。
文字列内の一重引用符または二重引用符は、バックスラッシュ(\)でエスケープする必要があります。
文字列内の改行(\n)はサポートされていません。
親トピック: カスタム・グラフ・データの読取り
6.3.4 エッジ・プロパティの追加
この例では、タイプstring
のエッジ・プロパティをグラフに追加します。エッジ・プロパティは、目標の頂点(ノード) IDに続いて配置されます。
"node1" 0.1 "node2" "edge_prop_1_2" "node2" 2.0 "node3" "edge_prop_2_3" "node4" "edge_prop_2_4" "node3" 0.3 "node4" "edge_prop_3_4" "node4" 4.56789 "node2" "edge_prop_4_2"
グラフ構成は、データ・ファイルと一致している必要があります。
JSON構成
{ "uri": "graph.adj", "format":"adj_list", "separator":" ", "node_props":[{ "name":"double-prop", "type":"double" }], "node_id_type":"string", "edge_props":[{ "name":"edge-prop", "type":"string" }] }
Java構成
import oracle.pgx.common.types.IdType; import oracle.pgx.common.types.PropertyType; import oracle.pgx.config.FileGraphConfig; import oracle.pgx.config.Format; import oracle.pgx.config.GraphConfigBuilder; FileGraphConfig config = GraphConfigBuilder.forFileFormat(Format.ADJ_LIST) .setUri("graph.adj") .setSeparator(" ") .addNodeProperty("double-prop", PropertyType.DOUBLE) .setNodeIdType(IdType.STRING) .addEdgeProperty("edge-prop", PropertyType.STRING) .build();
親トピック: カスタム・グラフ・データの読取り
6.4 グラフ・データのディスクへの格納
グラフはJavaまたはシェルを使用してメモリーに読み込んだ後、別の形式でディスクに格納できます。格納したグラフ・データは、後でインメモリー・アナリストへの入力として使用できます。
HTTP/RESTへのグラフの格納は現在サポートされていません。
オプションは、次のとおりです。
6.4.1 頂点プロパティへの分析結果の格納
これらの例では、グラフをメモリーに読み込み、Pagerankアルゴリズムを使用して分析します。この分析では、PageRank値を格納する新しい頂点プロパティが作成されます。
シェルを使用したPageRankの実行
pgx> g = session.readGraphWithProperties("/opt/oracle/oracle-spatial-graph/property_graph/examples/pgx/graphs/sample.adj.json", "my-graph") ==> ... pgx> rank = analyst.pagerank(g, 0.001, 0.85, 100)
Javaを使用したPageRankの実行
PgxGraph g = session.readGraphWithProperties("/opt/oracle/oracle-spatial-graph/property_graph/examples/pgx/graphs/sample.adj.json", "my-graph"); VertexProperty<Integer, Double> rank = session.createAnalyst().pagerank(g, 0.001, 0.85, 100);
JavaScriptを使用したPageRankの実行
let p = pgx.connect(url, options); p.then(function(session) { return session.readGraphWithProperties(jsonContent); }).then(function(graph) { return graph.session.analyst.pagerank(graph); });
親トピック: グラフ・データのディスクへの格納
6.4.2 エッジリスト形式でのグラフのディスクへの格納
この例では、グラフ、Pagerank分析の結果、および元のエッジ・プロパティすべてをエッジリスト形式でディスクに格納します。
グラフを格納するには、次を指定する必要があります。
-
グラフの形式
-
ファイルが格納されるパス
-
格納されるプロパティ。VertexProperty.
ALL
またはEdgeProperty.ALL
を指定するとすべてのプロパティが格納され、VertexProperty.NONE
またはEdgePropery.NONE
を指定すると、どのプロパティも格納されません。個々のプロパティを指定するには、格納するVertexPropertyまたはEdgePropertyオブジェクトを渡します。 -
既存のファイルを同じ名前で上書きするかどうかを示すフラグ
次の例では、/tmp/sample_pagerank.elist.json
構成ファイルでグラフ・データを/tmp/sample_pagerank.elist
に格納します。戻り値は、格納されているファイルのグラフ構成です。これは再度、グラフの読取りに使用できます。
シェルを使用したグラフの格納
pgx> config = g.store(Format.EDGE_LIST, "/tmp/sample_pagerank.elist", [rank], EdgeProperty.ALL, false) ==> {"uri":"/tmp/sample_pagerank.elist","edge_props":[{"type":"double","name":"cost"}],"vertex_id_type":"integer","loading":{},"format":"edge_list","attributes":{},"vertex_props":[{"type":"double","name":"pagerank"}],"error_handling":{}}
Javaを使用したグラフの格納
import oracle.pgx.api.*; import oracle.pgx.config.*; FileGraphConfig config = g.store(Format.EDGE_LIST, "/tmp/sample_pagerank.elist", Collections.singletonList(rank), EdgeProperty.ALL, false);
JavaScriptを使用したグラフの格納
let p = graph.store({format: 'EDGE_LIST', targetPath: '/tmp/sample_pagerank.elist'});
親トピック: グラフ・データのディスクへの格納
6.5 組込みアルゴリズムの実行
インメモリー・アナリストには、一連の組込みアルゴリズムが含まれており、Java APIとして使用できます。
このトピックでは、Triangle CountingおよびPagerank分析を使用したインメモリー・アナリストの使用方法について説明します。
6.5.1 インメモリー・アナリストについて
インメモリー・アナリストには、一連の組込みアルゴリズムが含まれており、Java APIとして使用できます。APIの詳細は、製品ドキュメント・ライブラリに含まれるJavadocに記載されています。特に、サポートされているインメモリー・アナリストのメソッドのリストについては、Analyst
クラスのメソッド・サマリーを参照してください。
たとえば、Pagerankプロシージャの署名は次のとおりです。:
/** * Classic pagerank algorithm. Time complexity: O(E * K) with E = number of edges, K is a given constant (max * iterations) * * @param graph * graph * @param e * maximum error for terminating the iteration * @param d * damping factor * @param max * maximum number of iterations * @return Vertex Property holding the result as a double */ public <ID> VertexProperty<ID, Double> pagerank(PgxGraph graph, double e, double d, int max);
親トピック: 組込みアルゴリズムの実行
6.5.2 Triangle Countingアルゴリズムの実行
Triangle Countingの場合、countTriangles()
のsortByDegree
ブール・パラメータを使用して、グラフを最初に角度でソートする(true
)かソートしない(false
)かを制御します。true
の場合、さらに多くのメモリーが使用されますが、アルゴリズムの実行は高速になります。ただし、グラフが非常に大きい場合、この最適化をオフにしてメモリー不足を回避する必要があります。
シェルを使用したTriangle Countingの実行
pgx> analyst.countTriangles(graph, true) ==> 1
Javaを使用したTriangle Countingの実行
import oracle.pgx.api.*; Analyst analyst = session.createAnalyst(); long triangles = analyst.countTriangles(graph, true);
JavaScriptを使用したTriangle Countingの実行
p.then(function(graph) { return graph.session.analyst.countTriangles(graph, true); })
このアルゴリズムでは、サンプル・グラフ内の1つの三角形を検出します。
ヒント:
インメモリー・アナリスト・シェルを使用する場合、ロギング・レベルを変更すると、実行中のログ出力の量を増加できます。:h :loglevel
を指定した:loglevel
コマンドの実行に関する情報を参照してください。
親トピック: 組込みアルゴリズムの実行
6.5.3 Pagerankアルゴリズムの実行
Pagerankは、グラフ内のそれぞれの頂点(ノード)について、0
と1
の間のランク値を計算し、その値をdouble
プロパティに格納します。このため、アルゴリズムによって、出力に対してタイプdouble
の頂点プロパティが作成されます。
インメモリー・アナリストでは、頂点プロパティとエッジ・プロパティの2つのタイプがあります。
-
永続プロパティ: データ・ソースからグラフとともにロードされ固定されたディスク上のデータのインメモリー・コピーであるため、永続となるプロパティ。永続プロパティは読取り専用のため変更できず、セッション間で共有されます。
-
一時プロパティ: 一時プロパティには値が書き込めるため、セッションでプライベートに使用されます。一時プロパティは、
PgxGraph
オブジェクトでcreateVertexProperty
およびcreateEdgeProperty
を呼び出して作成できます。
この例では、Pagerank値が最も高い上位3つの頂点を取得します。タイプdouble
の一時頂点プロパティを使用して、計算したPagerank値を保持します。Pagerankアルゴリズムでは、入力パラメータのデフォルト値としてエラー許容差 = 0.001、ダンピング係数 = 0.85、および反復の最大数 = 100のデフォルト値を使用します。
シェルを使用したPageRankの実行
pgx> rank = analyst.pagerank(graph, 0.001, 0.85, 100); ==> ... pgx> rank.getTopKValues(3) ==> 128=0.1402019732468347 ==> 333=0.12002296283541904 ==> 99=0.09708583862990475
Javaを使用したPageRankの実行
import java.util.Map.Entry; import oracle.pgx.api.*; Analyst analyst = session.createAnalyst(); VertexProperty<Integer, Double> rank = analyst.pagerank(graph, 0.001, 0.85, 100); for (Entry<Integer, Double> entry : rank.getTopKValues(3)) { System.out.println(entry.getKey() + "=" + entry.getValue()); }
JavaScriptを使用したPageRankの実行
p.then(function(graph) { return graph.session.analyst.pagerank(graph, {e: 0.001, d: 0.85, max: 100}); });
親トピック: 組込みアルゴリズムの実行
6.6 サブグラフの作成
メモリーにロードされたグラフに基づいてサブグラフを作成できます。
フィルタ式を使用するか、2部グラフの左側の集合を指定する頂点(ノード)に基づく2部サブグラフを作成できます。
グラフのメモリーへの読込みについては、「グラフ・データのメモリーへの読込み」を参照してください。
- フィルタ式について
- 簡易エッジ・フィルタを使用したサブグラフの作成
- 簡易頂点フィルタを使用したサブグラフの作成
- 複合フィルタを使用したサブグラフの作成
- 式フィルタの結合
- 式フィルタを使用した一連の頂点またはエッジの作成
- 頂点集合を使用した2部サブグラフの作成
親トピック: インメモリー・アナリスト(PGX)の使用
6.6.1 フィルタ式について
フィルタ式は、各頂点または各エッジで評価される式です。式によって、結果(この場合はサブグラフ)に含まれるようにエッジを完成させる述部を定義できます。
4つの頂点(ノード)と4つのエッジで構成される図6-1のグラフを検討します。フィルタ式src.prop1 == 10
と一致するエッジについては、元の頂点のprop
プロパティが10になります。図6-3に示すフィルタ式と一致する2つのエッジ。
次のエッジ・フィルタ式は、
src.prop1 == 10
ソース頂点のprop1
という名前のプロパティの値が10である各エッジがフィルタ式と一致するよう指定します。この場合、次のエッジが式と一致します。
-
頂点
id
: 128から頂点id
: 1908までを上部でつなぐエッジ(cost
: 27.03) -
頂点
id
: 128から頂点id
: 99までを左側でつなぐエッジ(cost
: 8.51)
図6-4は、前述のフィルタ式が適用されたときに生成されるサブグラフを示しています。このサブグラフには、id: 128を持つ頂点、左側と上部のエッジ、および各エッジの宛先頂点(id
: 1908およびid
: 99を持つ頂点)が含まれます。
次の頂点フィルタ式は、
vertex.prop1 < 10
prop1
という名前のプロパティの値が10未満である各頂点がフィルタ式と一致するよう指定します。この場合、次のエッジが式と一致します。
-
頂点
id
: 99から頂点id
: 333までを下部でつなぐエッジ(cost
: 338.0)
フィルタ式の例
-
日付。次の式は、エッジのプロパティ
date
にアクセスし、これが03/27/2007 06:00
と等しいかどうかを確認します。edge.date = date('2007-03-27 06:00:00')
-
入力/出力角度。
inDegree()
は頂点の入力エッジの数を返し、outDegree()
は頂点の出力エッジの数を返します。次の例では、srcは現在のエッジのソース(出力)頂点を示し、dstは宛先(入力)頂点を示します。src.inDegree() > 3 dst.outDegree() < 5
-
ラベル。
hasLabel
は、頂点に特定のラベルがある場合、true
を返します。次は、頂点にcity
ラベルがあり、そのpopulationが10000を超えている場合、true
を返します。vertex.hasLabel('city') && (vertex.population > 10000)
-
ラベル。
label
は、エッジのラベルを返します。次の例では、エッジのラベルがfriend_of
またはclicked_by
である場合、true
を返します。edge.label() = 'friend_of' || edge.label() = 'clicked_by'
-
型変換: 次の例では、ソース頂点のcostプロパティの値を整数に変換します。
(int) src.cost
-
算術のサポート: 次の例は、フィルタ式で使用できる算術式を示しています。
1 + 5 -vertex.degree() edge.cost * 2 > 5 src.value * 2.5 = (dst.inDegree() + 5) / dst.outDegree()
親トピック: サブグラフの作成
6.6.2 簡易エッジ・フィルタを使用したサブグラフの作成
次の例では、「フィルタ式について」で説明した最初のサブグラフを作成します。
シェルを使用したサブグラフの作成
subgraph = graph.filter(new EdgeFilter("src.prop1 == 10"))
Javaを使用したサブグラフの作成
import oracle.pgx.api.*; import oracle.pgx.api.filter.*; PgxGraph graph = session.readGraphWithProperties(...); PgxGraph subgraph = graph.filter(new EdgeFilter("src.prop1 == 10"));
JavaScriptを使用したサブグラフの作成
return graph.filter(pgx.createEdgeFilter("src.prop1 == 10"));
親トピック: サブグラフの作成
6.6.3 簡易頂点フィルタを使用したサブグラフの作成
次の例では、「フィルタ式について」で説明した2番目のサブグラフを作成します。
シェルを使用したサブグラフの作成
subgraph = graph.filter(new VertexFilter("vertex.prop1 < 10"))
Javaを使用したサブグラフの作成
import oracle.pgx.api.*; import oracle.pgx.api.filter.*; PgxGraph graph = session.readGraphWithProperties(...); PgxGraph subgraph = graph.filter(new VertexFilter("src.prop1 < 10"));
JavaScriptを使用したサブグラフの作成
return graph.filter(pgx.createVertexFilter("vertex.prop1 < 10"));
親トピック: サブグラフの作成
6.6.4 複合フィルタを使用したサブグラフの作成
この例では、少し複雑なフィルタを使用しています。ここでは、識別子の送信エッジの数(ソースsrc
または宛先dst
)を計算するoutDegree
関数を使用します。次のフィルタ式は、cost
プロパティ値が50を超え、outDegree
が1を超える宛先の頂点(ノード)のエッジと一致します。
dst.outDegree() > 1 && edge.cost > 50
図6-5では、サンプル・グラフのエッジの1つがこのフィルタ式と一致します。
図6-6はフィルタを適用した結果のグラフを示します。フィルタは頂点99と1908に対応するエッジを除外するため、その頂点も除外します。
親トピック: サブグラフの作成
6.6.5 式フィルタの結合
頂点フィルタをエッジ・フィルタと結合できます。
両方のフィルタが個別に評価され、後で次のいずれかを作成することによってマージされます。
-
結果の結合
-
結果の交差
2つのフィルタの結合の作成
結合の実行対象としてエッジ・フィルタと、
src.prop1 == 10
頂点フィルタを選択すると、
vertex.prop1 < 10
次のグラフに示す結果が得られます。
シェルの例:
edgeFilter = new EdgeFilter("src.prop1 == 10") vertexFilter = new VertexFilter("vertex.prop1 < 10") filter = edgeFilter.union(vertexFilter) subgraph = g.filter(filter)
Javaの例:
import oracle.pgx.api.filter.*; ... EdgeFilter edgeFilter = new EdgeFilter("src.prop1 == 10"); VertexFilter vertexFilter = new VertexFilter("vertex.prop1 < 10"); GraphFilter filter = edgeFilter.union(vertexFilter); PgxGraph subgraph = g.filter(filter);
JavaScriptの例:
return p.then(function(graph) { let edgeFilter = pgx.createEdgeFilter("src.prop1 == 10"); let vertexFilter = pgx.createVertexFilter("vertex.prop1 < 10"); let filter = edgeFilter.union(vertexFilter); return graph.filter(filter); });
2つのフィルタの交差の作成
結合の例で説明したフィルタの交差を作成すると、単一の頂点のみで構成された次のグラフが生成されます。
シェルの例:
edgeFilter = new EdgeFilter("src.prop1 == 10") vertexFilter = new VertexFilter("vertex.prop1 < 10") filter = edgeFilter.intersect(vertexFilter) subgraph = g.filter(filter)
Javaの例:
import oracle.pgx.filter.expressions.*; ... EdgeFilter edgeFilter = new EdgeFilter("src.prop1 == 10"); VertexFilter vertexFilter = new VertexFilter("vertex.prop1 < 10"); GraphFilter filter = edgeFilter.intersect(vertexFilter); PgxGraph subgraph = g.filter(filter);
JavaScriptの例:
return p.then(function(graph) { let edgeFilter = pgx.createEdgeFilter("src.prop1 == 10"); let vertexFilter = pgx.createVertexFilter("vertex.prop1 < 10"); let filter = edgeFilter.intersect(vertexFilter); return graph.filter(filter); });
親トピック: サブグラフの作成
6.6.6 式フィルタを使用した一連の頂点またはエッジの作成
式フィルタを使用したサブグラフの作成(他のトピックで説明しています)以外にも、式フィルタを使用してグラフから一連の頂点またはエッジのみを選択することもできます。
たとえば、次の頂点フィルタ式を使用して「フィルタ式について」のサンプル・グラフで頂点セットを作成できます。
vertex.prop1 < 10
これにより、ID値99および333を持つ頂点セットが生成されます。
例6-4 頂点セットの作成
シェルの例:
vertices = g.getVertices( new VertexFilter("vertex.prop1 < 10") ) ==> PgxVertex with ID 99 ==> PgxVertex with ID 333
Javaの例:
import oracle.pgx.api.*; import oracle.pgx.filter.expressions.*; ... VertexSet<Integer> = g.getVertices( new VertexFilter("vertex.prop1 < 10") );
例6-5 エッジ・セットの作成
シェルの例:
edges = g.getEdges( new EdgeFilter("src.prop1 == 10") ) ==> PgxEdge with ID 0 ==> PgxEdge with ID 1
Javaの例:
import oracle.pgx.api.*; import oracle.pgx.filter.expressions.*; ... EdgeSet = g.getEdges( new EdgeFilter("src.prop1 == 10") );
親トピック: サブグラフの作成
6.6.7 頂点集合を使用した2部サブグラフの作成
2部サブグラフは、左側に使用される頂点(ノード)集合を指定して作成できます。2部サブグラフには、左側の頂点集合と右側の頂点集合の間にのみエッジがあります。左側の2つのノード間など、これらの集合内にエッジはありません。インメモリー・アナリストでは、入力および出力エッジが削除されたために分離された頂点は、2部サブグラフの一部ではありません。
次の図は、2部サブグラフを示します。プロパティは示していません。
次の例では、図6-1で作成した単一のグラフから2部サブグラフを作成します。左側の頂点集合を作成し、それに頂点を入力します。
シェルを使用した2部サブグラフ作成
pgx> s = graph.createVertexSet() ==> ... pgx> s.addAll([graph.getVertex(333), graph.getVertex(99)]) ==> ... pgx> s.size() ==> 2 pgx> bGraph = graph.bipartiteSubGraphFromLeftSet(s) ==> PGX Bipartite Graph named sample-sub-graph-4
Javaを使用した2部サブグラフ作成
import oracle.pgx.api.*; VertexSet<Integer> s = graph.createVertexSet(); s.addAll(graph.getVertex(333), graph.getVertex(99)); BipartiteGraph bGraph = graph.bipartiteSubGraphFromLeftSet(s);
サブグラフを作成すると、インメモリー・アナリストで、頂点が左側にあるかどうかを示すブール頂点(ノード)プロパティが自動的に作成されます。このプロパティには一意の名前を指定できます。
結果の2部サブグラフは次のようになります。
頂点1908は2部サブグラフから除外されます。頂点に繋がっている唯一のエッジは、128から1908に伸びています。エッジはサブグラフの2部プロパティに反しているため削除されています。頂点1908にはその他のエッジがないため、これも削除されています。
親トピック: サブグラフの作成
6.7 グラフを使用したパターンマッチング問合せの使用
インメモリー・グラフに対してパターンマッチング問合せを発行してから、その問合せの結果を操作できます。
パターンマッチング問合せの例のデータ・セット
パターンマッチングの例では、2つの異なるデータ・セットを使用します。
-
政治家、スポーツ選手、著名人および会社の間の関係
-
装置、結線およびスイッチが含まれる電気ネットワーク
PGQLを使用したパターンマッチング問合せの発行
Property Graph Suery Language (PGQL)でグラフのパターンマッチング問合せを発行できます。PGQLは、SQLに似た宣言言語で、頂点とエッジ、および頂点とエッジのプロパティに関する制約で構成されたパターンを表現できます。
インメモリー・アナリストに対する問合せを発行するには、PgxGraph
(session
を使用してグラフをロードするときに取得するオブジェクトのタイプ)のqueryPgql()
Javaメソッドを使用するか、同等のJavaScript関数を使用できます。Javaの例:
次のトピックでは、問合せのパターンマッチングを使用します。
6.7.1 例: 敵の敵は味方である
このトピックの例では、古来の有名な格言である「敵の敵は味方である」から着想を得たグラフ・パターンについて説明します。特に、このグラフには、2つのfeuds
エッジ・ラベルによって接続された2つのエンティティが含まれます。頂点は、人々、一族または国を表します。互いに反目する頂点のペアは、feuds
エッジ・ラベルが付けられたエッジを持ちます。
このような問合せは、次のようにPGQLで作成されます。
SELECT x.name, z.name WHERE (x) -[e1:feuds]-> (y), (y) -[e2:feuds]-> (z), x != y ORDER BY x.name, z.name
この問合せでは、結果はx.name
によって順序付けされた後、z.name
順序付けされます。
PGXに対する問合せの発行:
シェルの例:
pgx> resultSet = connectionsGraph.queryPgql("SELECT x.name, z.name WHERE (x) -[e1:feuds]-> (y), (y) -[e2:feuds]-> (z), x != z ORDER BY x.name, z.name")
Javaの例:
import oracle.pgx.api.*; ... PgqlResultSet resultSet = connectionsGraph.queryPgql("SELECT x.name, z.name WHERE (x) -[e1:feuds]-> (y), (y) -[e2:feuds]-> (z), x != z ORDER BY x.name, z.name");
JavaScriptの例:
return p.then(function(graph) { return graph.queryPgql("SELECT x.name, z.name WHERE (x) -[e1:feuds]-> (y), (y) -[e2:feuds]-> (z), x != z ORDER BY x.name, z.name"); });
PgqlResultSet
は、問合せの結果セットを管理します。結果セットには、複数の結果が含まれます(このような問合せでは、多くのサブグラフが照合される場合があります)。各結果は、結果要素のリストで構成されています。結果要素の順序は、問合せのSELECT
句内の変数の順序に従います。
問合せ結果を反復することは、一連のPgqlResultElement
インスタンスを反復することを意味します。PgqlResultElement
は、結果要素の型および変数名を保持します。
PgqlResultElement
インスタンスのリストは、次のように取得できます。
シェルの例:
pgx> resultElements = resultSet.getPgqlResultElements()
Javaの例:
import oracle.pgx.api.*; import java.util.List; ... List<PgqlResultElement> resultElements = resultSet.getPgqlResultElements();
JavaScriptの例:
return p.then(function(resultSet) { console.log(resultSet.resultElements); });
最初の結果要素の型および変数名を取得します。
シェルの例:
pgx> resultElement = resultElements.get(0) pgx> type = resultElement.getElementType() // STRING pgx> varName = resultElement.getVarName() // x.name
Javaの例:
import oracle.pgx.api.*; ... PgqlResultElement resultElement = resultElements.get(0); PqglResultElement.Type = resultElement.getElementType(); // STRING String varName = resultElement.getVarName(); // x.name
JavaScriptの例:
return p.then(function(resultSet) { console.log(resultSet.resultElements[0].varName); console.log(resultSet.resultElements[0].elementType); });
ループのfor-eachスタイルを使用して結果セットを反復します。ループ内では、問合せ結果が含まれるPgqlResult
インスタンスを取得します。
シェルの例:
pgx> resultSet.getResults().each { \ // the variable 'it' is implicitly declared to references each PgqlResult instance }
Javaの例:
import oracle.pgx.api.*; ... for (PgqlResult result : resultSet.getResults()) { ... }
JavaScriptの例:
return p.then(function(resultSet) { return resultSet.iterate(function(row) { console.log(row); }); });
シェル内では、PqglResultSet
のprint
メソッドを使用してテキスト形式で結果セットを適切に印刷できます。
pgx> resultSet.print(10) // print the first 10 results
次の結果が表示されます。
-------------------------------- | x.name | z.name | ================================ | ABC | CBS | | ABC | NBC | | Alibaba | Beyonce | | Alibaba | Google | | Alibaba | eBay | | Amazon | Carl Icahn | | Amazon | Facebook | | Amazon | Tencent | | Angela Merkel | Barack Obama | | Angela Merkel | John Kerry | --------------------------------
個々のPgqlResult
インスタンスまたはそれらの要素のハンドルを取得することもできます。
結果要素の索引別:
pgx> nameX = it.getString(0) pgx> nameZ = it.getString(1)
結果要素の変数名別:
pgx> nameX = it.getString("x.name") pgx> nameZ = it.getString("z.name")
型を知らずに結果要素を取得することもできます。
pgx> nameX = it.get(0) // or pgx> nameX = it.get("x.name")
JavaScriptでは、次のように変数名別に結果要素にアクセスできます。
return p.then(function(resultSet) { return resultSet.iterate(function(row) { console.log(row['n']); console.log(row['n.pagerank']); }); });
親トピック: グラフを使用したパターンマッチング問合せの使用
6.7.2 例: 協力者の最も多い上位10人
この例では、グラフ内の協力者の最も多い上位10人を協力者の数の降順で見つけます。このような問合せではPGQLの様々な機能を活用しますが、これには、WHERE句で見つかったグラフ・パターンのグループ化、集計、順序付けおよび制限が含まれます。次の問合せ文字列は、PGQLでのユーザーの照会を表します。
pgx> resultSet = connectionsGraph.queryPgql("SELECT x.name, COUNT(*) AS num_collaborators WHERE (x) -[:collaborates]-> () GROUP BY x ORDER BY DESC(num_collaborators) LIMIT 10")
この問合せでは、次の処理を実行します。
-
`collaborates'エッジ・ラベルを照合することにより、グラフから協力関係パターンをすべて見つけます。
-
見つかったパターンをソース頂点別にグループ化します。
-
各グループにカウント集計を適用し、協力者の数を見つけます。
-
協力者の数別に降順でグループに順序を付けます。
-
最初の10個の結果のみを採用します。
print()
メソッドは、グラフ内で協力者の最も多い上位10人の名前および協力者の数を表示します。
pgx> resultSet.print()
次の結果が表示されます。
--------------------------------------------------- | x.name | num_collaborators | =================================================== | Barack Obama | 10 | | Charlie Rose | 4 | | Omar Kobine Layama | 3 | | Dieudonne Nzapalainga | 3 | | Nicolas Guerekoyame Gbangou | 3 | | NBC | 3 | | Pope Francis | 3 | | Beyonce | 2 | | Eric Holder | 2 | | Tom Steyer | 2 | ---------------------------------------------------
親トピック: グラフを使用したパターンマッチング問合せの使用
6.7.3 例: 電気装置間の推移的な接続性
この例では、頂点間で到達可能性をテストします。ここでは、次の図の電気ネットワークのグラフを使用します。
この例では、グラフ内のすべてのDevice
が他のすべてのDevice
と推移的に接続されているかどうかを確認しようとしてします。装置は、Connection
頂点およびSwitch
頂点によって接続されています。
最初に、次のPGQL問合せを発行することにより、グラフ内にいくつの装置があるか確認します。
SELECT COUNT(*) AS numDevices WHERE (n:Device)
結果は6031です。
-------------- | numDevices | ============== | 6031 | --------------
装置ごとに、ゼロ以上Connection
またはSwitch
頂点(および必要なエッジ)を辿ることによって到達できる装置の数を計算します。この問合せは、次のようにPGQLで表すことができます。
PATH connects_to := () <- (/*:Connection|Switch*/) -> () SELECT n.nickname AS device, count(m) AS reachabilityCount WHERE (n:Device) -/:connects_to*/-> (m:Device) GROUP BY n ORDER BY COUNT(m), n.nickname
この問合せでは、隣接する2つの装置/接続の間の明確な接続がパス・パターンconnects_to
を使用して表されています。クリーネ・スター(*)は、推移的接続を確認することを目的として、パス・パターンがゼロ以上の回数繰り返して一致する可能性があることを表しています。(インメモリー・アナリストではこの機能がまだサポートされていないため、パス・パターン内のラベルはコメントアウトされます。)
この問合せでは、GROUP BY
を使用して、ソース装置n
ごとにグループを作成してから、到達可能な宛先装置m
の数を計算します。最初の20の結果は次のとおりです。
------------------------------------------------ | device | reachabilityCount | ================================================ | 190-7361-M1089120 | 6031 | | 190-8581-D5587291-3_INT | 6031 | | 190-8593-D5860423-3_INT | 6031 | | 196-29518-L3122816 | 6031 | | 196-29519-L3066815 | 6031 | | 196-29520-L3160109 | 6031 | | 196-29521-N1136355 | 6031 | | 196-31070-D5861005-2_INT | 6031 | | 196-35541-M1108317 | 6031 | | 196-35813-N1140519 | 6031 | | 196-36167-L3011298 | 6031 | | 198-5320-221-311359 | 6031 | | 221-240988-L3141411 | 6031 | | 221-240991-L3066817 | 6031 | | 221-242079-L3011293 | 6031 | | 221-282818-N1230123 | 6031 | | 221-282819-N1230122 | 6031 | | 221-306686-L2970258 | 6031 | | 221-306687-L2916625 | 6031 | | 221-308718-L2803199 | 6031 | ------------------------------------------------
結果はreachabilityCount
の数を増加させることによってソートされるため、および結果内の最初の装置でさえグラフ内のすべての装置に推移的に接続されるため(reachabilityCount = 6031
)、ここでは、グラフ内のすべての装置が相互に完全に到達可能であることが分かります。
親トピック: グラフを使用したパターンマッチング問合せの使用
6.8 インメモリー・アナリスト・サーバーの起動
Big Data Spatial and Graphには、スクリプトの実行によってインメモリー・アナリスト・サーバーを起動できるApache Tomcatの事前構成済バージョンがバンドルされています。
サーバーを起動する前に構成する必要がある場合は、「インメモリー・アナリスト・サーバーの構成」を参照してください。
サーバーを起動するには、スクリプト/opt/oracle/oracle-spatial-graph/property_graph/pgx/bin/start-server
を実行します
6.8.1 インメモリー・アナリスト・サーバーの構成
インメモリー・アナリスト・サーバーは、/opt/oracle/oracle-spatial-graph/property_graph/pgx/conf/server.confファイルを変更することによって構成できます。次の表は、JSON形式で指定できる有効な構成オプションを示します。
表6-2 インメモリー・アナリスト・サーバーの構成オプション
オプション | 型 | 説明 | デフォルト |
---|---|---|---|
authorization |
string |
クライアントを認可のロールにマップするファイル。 |
server.auth.conf |
ca_certs |
stringの配列 |
信頼できる証明書のリスト(PEM形式)。'enable_tls'がfalseに設定されている場合、このオプションは無効です。 |
[この表の後の情報を参照してください。] |
enable_client_authentication |
boolean |
trueの場合、クライアントはTLSハンドシェイク時に認証されます。詳細は、TLSプロトコルを参照してください。'enable_tls'がfalseである場合、このフラグは無効です。 |
true |
enable_tls |
boolean |
trueの場合、トランスポート層セキュリティ(TLS)が有効になります。 |
true |
port |
integer |
PGXサーバーがリッスンする必要があるポート |
7007 |
server_cert |
string |
TLSクライアントに提示されるサーバー証明書へのパス(PEM形式)。'enable_tls'がfalseに設定されている場合、このオプションは無効です |
null |
server_private_key |
string |
サーバーの秘密鍵(PKCS#8、PEM形式)。'enable_tls'がfalseに設定されている場合、このオプションは無効です |
null |
インメモリー・アナリストWebサーバーを使用すると、デフォルトで双方向のSSL/TLS (トランスポート層セキュリティ)が有効になります。このサーバーでは、TLS 1.2が適用され、攻撃に対して脆弱であることが知られている特定の暗号スイートが無効になります。TLSハンドシェイク時には、サーバーとクライアントの両方が相互に証明書を提示し合い、これらを使用して相手側の信頼性が検証されます。クライアント・アプリケーションの認可にはクライアント証明書も使用されます。
次に、server.conf
構成ファイルの例を示します。
{ "port": 7007, "server_cert": "certificates/server_certificate.pem", "server_private_key": "certificates/server_key.pem", "ca_certs": [ "certificates/ca_certificate.pem" ], "authorization": "auth/server.auth.conf", "enable_tls": true, "enable_client_authentication": true }
次に、server.auth.conf
構成ファイルの例を示します。マッピング・クライアント(アプリケーション)は、ロールに対する証明書のDN文字列によって識別されます。
{ "authorization": [{ "dn": "CN=Client, OU=Development, O=Oracle, L=Belmont, ST=California, C=US", "admin": false }, { "dn": "CN=Admin, OU=Development, O=Oracle, L=Belmont, ST=California, C=US", "admin": true }] }
サーバー構成ではクライアント側の認証またはSSL/TLS認証全体をオフにすることができます。ただし、任意の本番環境に対して双方向のSSL/TLSを有効にすることをお薦めします。
親トピック: インメモリー・アナリスト・サーバーの起動
6.9 Jettyへのデプロイ
インメモリー・アナリストは、Eclipse Jetty、Apache Tomcat、またはOracle WebLogic Serverにデプロイできます。この例では、Webアプリケーションとしてインメモリー・アナリストをEclipse Jettyにデプロイする方法を示しています。
注意:
これらの手順は、インメモリー・アナリストのテストのみを目的としています。本格的なデプロイメントの場合、正しい認証および認可を適用し、資格情報を安全に格納し、HTTPSを介して接続のみを許可するよう、Jettyを構成する必要があります。
-
インメモリー・アナリストのWebアプリケーション・アーカイブ(WAR)ファイルをJettyの
webapps
ディレクトリにコピーします(<VERSION>
を実際のバージョン番号に置き換えます)。cp $PGX_HOME/server/shared-mem/pgx-webapp-<VERSION>.war.war $JETTY_HOME/webapps/pgx.war
-
ポート8080が未使用であることを確認し、Jettyを開始します。
cd $JETTY_HOME java -jar start.jar
-
Jettyが動作していることを確認します。
cd $PGX_HOME ./bin/pgx --base_url http://localhost:8080/pgx
-
(オプション)インメモリー・アナリスト構成ファイルを変更します。
インメモリー・アナリスト・エンジンの構成ファイル(
pgx.conf
)およびロギング・パラメータ(log4j.xml
)は、WEB-INF/classes
のWARファイル内にあります。変更を行った後、サーバーを再起動して変更を有効にします。
関連項目:
http://eclipse.org/jetty/documentation/
にある構成および使用に関するJettyドキュメント
親トピック: インメモリー・アナリスト(PGX)の使用
6.10 Apache Tomcatへのデプロイ
インメモリー・アナリストは、Eclipse Jetty、Apache Tomcat、またはOracle WebLogicにデプロイできます。この例では、Webアプリケーションとしてインメモリー・アナリストをApache Tomcatにデプロイする方法を示しています。
注意:
これらの手順は、インメモリー・アナリストのテストのみを目的としています。本格的なデプロイメントの場合、正しい認証および認可を適用し、資格情報を安全に格納し、HTTPSを介して接続のみを許可するよう、Apache Tomcatを構成する必要があります。
親トピック: インメモリー・アナリスト(PGX)の使用
6.11 Oracle WebLogic Serverへのデプロイ
インメモリー・アナリストは、Eclipse Jetty、Apache Tomcat、またはOracle WebLogic Serverにデプロイできます。この例では、Webアプリケーションとしてインメモリー・アナリストをOracle WebLogic Serverにデプロイする方法を示しています。
注意:
これらの手順は、インメモリー・アナリストのテストのみを目的としています。本格的なデプロイメントの場合、正しい認証および認可を適用し、資格情報を安全に格納し、HTTPSを介して接続のみを許可するよう、WebLogic Serverを構成する必要があります。
6.11.1 Oracle WebLogic Serverのデプロイ
Oracle WebLogic Serverの最新バージョンをダウンロードし、インストールするには、次を参照してください
http://www.oracle.com/technetwork/middleware/weblogic/documentation/index.html
親トピック: Oracle WebLogic Serverへのデプロイ
6.11.2 インメモリー・アナリストのデプロイ
Oracle WebLogicにインメモリー・アナリストをデプロイするには、次のようなコマンドを使用します。ユーザーの管理資格証明とWARファイルをこの例に示す値に入力します。
. $MW_HOME/user_projects/domains/mydomain/bin/setDomainEnv.sh . $MW_HOME/wlserver/server/bin/setWLSEnv.sh java weblogic.Deployer -adminurl http://localhost:7001 -username username -password password -deploy -source $PGX_HOME/server/pgx-webapp-wls.war
スクリプトが正常に実行されると、次のようなメッセージが表示されます。
Target state: deploy completed on Server myserver
親トピック: Oracle WebLogic Serverへのデプロイ
6.11.3 サーバーが動作していることの確認
サーバーに接続できることを確認します。
$PGX_HOME/bin/pgx --base_url http://localhost:7001/pgx
親トピック: Oracle WebLogic Serverへのデプロイ
6.12 インメモリー・アナリスト・サーバーへの接続
プロパティ・グラフのインメモリー・アナリストがサーバーとしてデプロイされ、Hadoopクラスタ(またはEclipse Jetty、Apache Tomcat、Oracle WebLogic上のWebアプリケーションとしてHadoopのないクライアント・システム)にインストールされた後、インメモリー・アナリスト・サーバーに接続できます。
6.12.1 インメモリー・アナリスト・シェルによる接続
インメモリー・アナリスト・インスタンスへの最も単純な接続方法は、サーバーのベースURLを指定することです。
--base_url
コマンド・ライン引数を使用して、そのベースURL上で実行されているサーバーに接続できます。たとえば、サーバーのSSL/TLSが無効であり、認証が必要なく、サーバーがhttp://localhost:8080/pgx
上で実行されている場合、次を入力することにより、PGXシェルを使用してサーバーに接続できます。
cd $PGX_HOME ./bin/pgx --base_url http://scott:<password>@localhost:8080/pgx
同じ方法でリモート・インスタンスに接続できます。
サーバーにBASIC認証が必要である場合、次の例のようにユーザー名およびパスワードを指定できます。
./bin/pgx --base_url http://localhost:8080/pgx --username scott --password <password-for-scott>
サーバーのSSL/TLSが有効である場合、--truststore
オプションを使用して、サーバー証明書を検証するために使用される信頼ストアへのパスを(JKS形式で)指定できます。
./bin/pgx --base_url https://localhost:8080/pgx --truststore path/to/truststore.jks
サーバーの双方向SSL/TLSが有効である場合、--keystore
および–-password
オプションを使用して、クライアント証明書およびキーストア・パスワードが含まれるキーストア・ファイルを指定できます。
./bin/pgx --base_url https://localhost:8080/pgx --truststore path/to/truststore.jks --keystore path/to/keystore.jks --password <password>
6.12.1.1 HTTPリクエストのロギングについて
インメモリー・アナリスト・シェルでは、デフォルトでデバッグ・メッセージをすべて非表示にします。どのHTTPリクエストが実行されたかを確認するには、この例に示すように、oracle.pgx
のログ・レベルをDEBUG
に設定します。
pgx> :loglevel oracle.pgx DEBUG ===> log level of oracle.pgx logger set to DEBUG pgx> session.readGraphWithProperties("sample_http.adj.json", "sample") 10:24:25,056 [main] DEBUG RemoteUtils - Requesting POST http://scott:<password>@localhost:8080/pgx/core/session/session-shell-6nqg5dd/graph HTTP/1.1 with payload {"graphName":"sample","graphConfig":{"uri":"http://path.to.some.server/pgx/sample.adj","separator":" ","edge_props":[{"type":"double","name":"cost"}],"node_props":[{"type":"integer","name":"prop"}],"format":"adj_list"}} 10:24:25,088 [main] DEBUG RemoteUtils - received HTTP status 201 10:24:25,089 [main] DEBUG RemoteUtils - {"futureId":"87d54bed-bdf9-4601-98b7-ef632ce31463"} 10:24:25,091 [pool-1-thread-3] DEBUG PgxRemoteFuture$1 - Requesting GET http://scott:<password>@localhost:8080/pgx/future/session/session-shell-6nqg5dd/result/87d54bed-bdf9-4601-98b7-ef632ce31463 HTTP/1.1 10:24:25,300 [pool-1-thread-3] DEBUG RemoteUtils - received HTTP status 200 10:24:25,301 [pool-1-thread-3] DEBUG RemoteUtils - {"stats":{"loadingTimeMillis":0,"estimatedMemoryMegabytes":0,"numEdges":4,"numNodes":4},"graphName":"sample","nodeProperties":{"prop":"integer"},"edgeProperties":{"cost":"double"}}
親トピック: インメモリー・アナリスト・シェルによる接続
6.12.2 Javaによる接続
Javaを使用してインメモリー・アナリストを初期化する場合、ベースURLを指定できます。この例は次のようになります。インメモリー・アナリスト・サーバーへのURLは、getInstance
API呼出しに提供されます。
import oracle.pg.nosql.*; import oracle.pgx.api.*; PgNosqlGraphConfig cfg = GraphConfigBuilder.forNosql().setName("mygraph").setHosts(...).build(); OraclePropertyGraph opg = OraclePropertyGraph.getInstance(cfg); ServerInstance remoteInstance = Pgx.getInstance("http://scott:tiger@hostname:port/pgx"); PgxSession session = remoteInstance.createSession("my-session"); PgxGraph graph = session.readGraphWithProperties(opg.getConfig());
Javaを使用した接続時に信頼ストア、キーストア、およびキーストア・パスワードを指定するには、javax.net.ssl.trustStore
、javax.net.ssl.keyStore
およびjavax.net.ssl.keyStorePassword
システム・プロパティをそれぞれ設定する必要があります。
親トピック: インメモリー・アナリスト・サーバーへの接続
6.12.3 JavaScriptによる接続
JavaScriptを使用してインメモリー・アナリストを初期化する場合、ベースURLを指定できます。この例は次のようになります。インメモリー・アナリスト・サーバーへのURLは、connect
API呼出しに提供されます。
const pgx = require('oracle-pgx-client'); // oracle-pgx-client npm package const fs = require('fs'); // options to connect to pgx server let options = { clientKey: fs.readFileSync('client_key.pem'), clientCert: fs.readFileSync('client_cert.pem'), caCert: fs.readFileSync('ca_cert.pem'), passphrase: 'passphrase', }; // connect to pgx server let p = pgx.connect(url, options).then(function(session) { return session.readGraphWithProperties(���); // load graph from pgx server }).then(function(graph) { return graph.session.analyst.pagerank(graph); // run pagerank algorithm in pgx server }).catch(function(err) { console.log("error: " + err); });
親トピック: インメモリー・アナリスト・サーバーへの接続
6.13 分散モードのインメモリー・アナリストの使用
インメモリー・アナリストは、共有メモリー・モードまたは分散モードで実行できます。
-
共有メモリー・モード
複数のスレッドが、単一のノード(単一の共有メモリー・スペース)に格納されているインメモリー・グラフ・データ上で並列して機能します。共有メモリー・モードでは、グラフのサイズは、物理メモリー・サイズによって、および同じノード上で実行されている他のアプリケーションによって制約されます。
-
分散モード
共有メモリー・モードの制限を克服するには、インメモリー・アナリストを分散モードで実行します。これにより、複数のノード(コンピュータ)がクラスタを形成し、分散メモリー全体にわたって大規模なプロパティ・グラフをパーティション化し、連携して機能することにより、効率的かつスケーラブルなグラフ分析を実現します。
インメモリー・アナリスト機能を分散モードで使用する場合、クラスタ内のノードごとに次の要件が適用されます。
-
GNU Compiler Collection (GCC) 4.8.2以降
GNU C++ APIの3.4.20上で構築されたC++標準ライブラリが必要です。
-
TCPポートを開く機能
分散インメモリー・アナリストでは、初期ハンドシェイクのために指定されたTCPポートを開くことが必要です。デフォルトのポート番号は7777ですが、ランタイム・パラメータ
pgx_side_channel_port
を使用して設定することもできます。 -
イーサネットでインフィニバンドまたはUDPを使用する機能
ノード間のデータ通信には主に、イーサネット上のインフィニバンド(IB)またはUDPが使用されます。イーサネットを使用する場合、クラスタ内のマシンが他のコンピュータからUDPパケットを受け取ることが必要です。
-
JDK8以降
インメモリー・アナリストを分散モードで起動するには、次の手順を実行します。(この例では、この目的のために4つのモード(コンピュータ)が割り当てられており、これらがホスト名hostname0
、hostname1
、hostname2
およびhostname3
を持つことを前提としています。)
ノードごとに、ログインして次の操作を実行します(実際の環境に応じて詳細を変更します)。
export PGX_HOME=/opt/oracle/oracle-spatial-graph/property_graph/pgx
export LD_LIBRARY_PATH=$PGX_HOME/server/distributed/lib:$JAVA_HOME/jre/lib/amd64/server:$LD_LIBRARY_PATH
cd $PGX_HOME/server/distributed
./bin/node ./package/main/ClusterHost.js -server_config=./package/options.json -pgx_hostnames=hostname0,hostname1,hostname2,hostname3
4つのノードすべてで操作が正常に完了した後、次のようなログ・メッセージを参照できます。
17:11:42,709 [hostname0] INFO pgx.dist.cluster_host - PGX.D Server listening on http://hostname0:8023/pgx
これで、分散モードのインメモリー・アナリストは起動して稼働しています。そのサービスはエンドポイントhttp://hostname0:8023/pgx
を介して提供されます
このエンドポイントは、リモートでデプロイされた共有メモリー・アナリストと同じ方法で使用できます。Java API、GroovyシェルおよびPGXシェルを使用できます。PGXシェルの使用例は、次のとおりです。
cd $PGX_HOME
./bin/pgx --base_url=http://hostname0:8023/pgx
次の例では、Oracle NoSQL Database用のGroovyシェルのサービスを使用します。
opg-nosql> session=Pgx.createSession("http://hostname0:8023/pgx", "session-id-123");
opg-nosql> analyst=session.createAnalyst();
opg-nosql> pgxGraph = session.readGraphWithProperties(opg.getConfig());
options.json
ファイルの例を次に示します。
$ cat ./package/options.json { "pgx_use_infiniband": 1, "pgx_command_queue_path": ".", "pgx_builtins_path": "./lib", "pgx_executable_path": "./bin/pgxd", "java_class_path": "./jlib/*", "pgx_httpserver_port": 8023, "pgx_httpserver_enable_csrf_token": 1, "pgx_httpserver_enable_ssl": 0, "pgx_httpserver_client_auth": 1, "pgx_httpserver_key": "<INSERT_VALUE_HERE>/server_key.pem", "pgx_httpserver_cert": "<INSERT_VALUE_HERE>/server_cert.pem", "pgx_httpserver_ca": "<INSERT_VALUE_HERE>/server_cert.pem", "pgx_httpserver_auth": "<INSERT_VALUE_HERE>/server.auth.json", "pgx_log_configure": "./package/log4j.xml", "pgx_ranking_query_max_cache_size": 1048576, "zookeeper_timeout": 10000, "pgx_partitioning_strategy": "out_in", "pgx_partitioning_ignore_ghostnodes": false, "pgx_ghost_min_neighbors": 5000, "pgx_ghost_max_node_counts": 40000, "pgx_use_bulk_communication": true, "pgx_num_worker_threads": 28 }
親トピック: インメモリー・アナリスト(PGX)の使用
6.14 HDFSでのデータの読取りおよび格納
インメモリー・アナリストでは、Hadoop Distributed File System (HDFS)をサポートしています。この例では、インメモリー・アナリストAPIを使用してHDFSのグラフ・データを読み取り、アクセスする方法を示しています。
グラフ構成ファイルはクライアント側で解析されます。グラフ・データと構成ファイルはHDFSに格納されます。Hadoopクライアントはインメモリー分析と同じコンピュータにインストールする必要があります。『Oracle Big Data Applianceソフトウェア・ユーザーズ・ガイド』を参照してください。
注意:
インメモリー・アナリスト・エンジンは、Hadoopクラスタの1つのノードのメモリーでのみ実行されます。
6.14.1 HDFSからのデータの読込み
この例では、sample.adj
グラフ・データとその構成ファイルをHDFSにコピーし、それをメモリーに読み込みます。
-
グラフ・データをHDFSにコピーします。
cd $PGX_HOME hadoop fs -mkdir -p /user/pgx hadoop fs -copyFromLocal ../examples/pgx/graphs/sample.adj /user/pgx
-
グラフ構成ファイル
sample.adj.json
のuri
フィールドを、HDFSリソースを指し示すように編集します。{ "uri": "hdfs:/user/pgx/sample.adj", "format": "adj_list", "node_props": [{ "name": "prop", "type": "integer" }], "edge_props": [{ "name": "cost", "type": "double" }], "separator": " " }
-
構成ファイルをHDFSにコピーします。
cd $PGX_HOME hadoop fs -copyFromLocal ../examples/pgx/graphs/sample.adj.json /user/pgx
-
次の例に示すように、HDFSからサンプル・グラフをインメモリー・アナリストに読み込みます。
シェルを使用したHDFSからのグラフの読込み
g = session.readGraphWithProperties("hdfs:/user/pgx/sample.adj.json"); ===> PgxGraph[name=sample,N=4,E=4,created=1475525438479]
Javaを使用したHDFSからのグラフの読込み
import oracle.pgx.api.*; PgxGraph g = session.readGraphWithProperties("hdfs:/user/pgx/sample.adj.json");
親トピック: HDFSでのデータの読取りおよび格納
6.14.2 グラフ・スナップショットのHDFSへの格納
インメモリー・アナリストのバイナリ形式(.pgb
)は、インメモリー・アナリスト独自のバイナリ・グラフ形式です。基本的に、.pgb
ファイルはグラフとそのプロパティ・データのバイナリ・ダンプであり、インメモリー・アナリスト操作を効率的にします。この形式を使用すると、グラフ・スナップショットをディスクにすぐにシリアル化し、後でメモリーに読み込んで戻すことができます。
既存の.pgb
ファイルは変更しないでください。
次の例では、HDFSで、現在メモリー内にあるサンプル・グラフをPGB形式でHDFSに格納します。
シェルを使用したグラフのHDFSへの格納
g.store(Format.PGB, "hdfs:/user/pgx/sample.pgb", VertexProperty.ALL, EdgeProperty.ALL, true)
Javaを使用したグラフのHDFSへの格納
import oracle.pgx.config.GraphConfig; import oracle.pgx.api.*; GraphConfig pgbGraphConfig = g.store(Format.PGB, "hdfs:/user/pgx/sample.pgb", VertexProperty.ALL, EdgeProperty.ALL, true);
PGBファイルが作成されたことを確認するには、/user/pgx
HDFSディレクトリでファイルをリストします。
hadoop fs -ls /user/pgx
親トピック: HDFSでのデータの読取りおよび格納
6.14.3 HadoopでのJavaアプリケーションのコンパイルおよび実行
前の例のHdfsDemo
Javaクラスを次に示します。
import oracle.pgx.api.Pgx; import oracle.pgx.api.PgxGraph; import oracle.pgx.api.PgxSession; import oracle.pgx.api.ServerInstance; import oracle.pgx.config.Format; import oracle.pgx.config.GraphConfig; import oracle.pgx.config.GraphConfigFactory; public class HdfsDemo { public static void main(String[] mainArgs) throws Exception { ServerInstance instance = Pgx.getInstance(Pgx.EMBEDDED_URL); instance.startEngine(); PgxSession session = Pgx.createSession("my-session"); GraphConfig adjConfig = GraphConfigFactory.forAnyFormat().fromPath("hdfs:/user/pgx/sample.adj.json"); PgxGraph graph1 = session.readGraphWithProperties(adjConfig); GraphConfig pgbConfig = graph1.store(Format.PGB, "hdfs:/user/pgx/sample.pgb"); PgxGraph graph2 = session.readGraphWithProperties(pgbConfig); System.out.println("graph1 N = " + graph1.getNumVertices() + " E = " + graph1.getNumEdges()); System.out.println("graph2 N = " + graph1.getNumVertices() + " E = " + graph2.getNumEdges()); } }
これらのコマンドは、HdfsDemo
クラスをコンパイルします。
cd $PGX_HOME mkdir classes javac -cp ../lib/'*' HdfsDemo.java -d classes
このコマンドはHdfsExample
クラスを実行します。
java -cp ../lib/*:conf:classes:$HADOOP_CONF_DIR HdfsDemo
親トピック: HDFSでのデータの読取りおよび格納
6.15 YARNアプリケーションとしてのインメモリー・アナリストの実行
この例では、Hadoop NextGen MapReduce (YARN)スケジューリングにより、Hadoopクラスタ上でインメモリー・アナリスト・サーバーを開始、停止および監視する方法について説明します。
6.15.1 インメモリー・アナリスト・サービスの開始および停止
YARNアプリケーションとしてインメモリー・アナリストを開始する前に、インメモリー・アナリストYARNクライアントを構成する必要があります。
6.15.1.1 インメモリー・アナリストYARNクライアントの構成
インメモリー・アナリスト・ディストリビューションには、$PGX_HOME/conf/yarn.conf
のYARNクライアント構成ファイルのサンプルが含まれています。
必要なフィールドがすべて設定されていることを確認します。指定したパスがHDFSにあり、zookeeper_connect_string
がCDHクラスタで実行中のZooKeeperポートを指し示している必要があります。
親トピック: インメモリー・アナリスト・サービスの開始および停止
6.15.1.2 新規インメモリー・アナリスト・サービスの開始
新規インメモリー・アナリスト・サービスをHadoopクラスタで開始するには、次のコマンドを使用します(<VERSION>を実際のバージョン番号に置き換えます)。
yarn jar $PGX_HOME/yarn/pgx-yarn-<VERSION>.jar
$PGX_HOME/conf/yarn.conf
以外のYARNクライアント構成ファイルを使用するには、ファイル・パスを指定します(<VERSION>を実際のバージョン番号に置き換え、/path/to/different/を実際のパスに置き換えます)。
yarn jar $PGX_HOME/yarn/pgx-yarn-<VERSION>.jar /path/to/different/yarn.conf
サービスが開始されると、インメモリー・アナリスト・サービスが起動されているHadoopノードのホスト名とポートが表示されます。
親トピック: インメモリー・アナリスト・サービスの開始および停止
6.15.1.3 長期実行インメモリー・アナリスト・サービスについて
インメモリー・アナリストYARNアプリケーションは、指定した時間後にタイムアウトするようにデフォルトで構成されています。pgx_server_timeout_secs
を0
に設定してタイムアウトを無効にすると、インメモリー・アナリスト・サーバーはユーザーまたはHadoopによって明示的に停止されるまで継続して実行されます。
親トピック: インメモリー・アナリスト・サービスの開始および停止
6.15.1.4 インメモリー・アナリスト・サービスの停止
実行中のインメモリー・アナリスト・サービスを停止する手順:
yarn application -kill appId
この構文では、appIdがサービス開始時に表示されるアプリケーションIDです。
終了したインメモリー・アナリスト・サービスのログを検証する手順:
yarn logs -applicationId appId
親トピック: インメモリー・アナリスト・サービスの開始および停止
6.15.2 インメモリー・アナリスト・サービスへの接続
YARNのインメモリー・アナリスト・サービスには、任意のインメモリー・アナリスト・サーバーに接続する場合と同じ方法で接続できます。たとえば、シェル・インタフェースでインメモリー・アナリスト・サービスに接続するには、次のようなコマンドを使用します。
$PGX_HOME/bin/pgx --base_url username:password@hostname:port
この構文では、usernameおよびpasswordがYARN構成で指定されているものと一致します。
6.16 Oracleの2つの表関係形式の使用
リレーショナル・データ・モデルを使用する場合、グラフ・データは2つのリレーショナル表を使用して表現できます。1つの表はノードとそのプロパティ用で、もう1つの表はエッジとそのプロパティ用です。
インメモリー・アナリストでは、2つのリレーショナル(RDBMS)表がノードとエッジを表すようなリレーショナル・グラフ表現でグラフを読み込むことができます。必要なのは、グラフのconfig
オブジェクトで次の追加フィールドを指定することのみです。
表6-3 2つの表形式の追加フィールド
フィールド | 型 | 説明 | デフォルト |
---|---|---|---|
edges_key_column |
string |
エッジ表内の主キー列の名前 |
eid |
edges_table_name |
string |
エッジ表の名前 |
null |
from_nid_column |
string |
ソース・ノードの列名 |
svid |
insert_batch_size |
integer |
挿入する行のバッチ・サイズ |
10000 |
max_prefetched_rows |
integer |
ラウンドトリップ時にプリフェッチされた行の最大数(結果セット - データベース)。 |
10000 |
nodes_key_column |
string |
ノード表内の主キー列の名前 |
vid |
nodes_table_name |
string |
ノード表の名前 |
null |
num_connections |
integer |
2つの表から/にデータを読み取る/書き込むための接続数 |
<no-of-cpus> |
schema |
string |
表の書込み先のスキーマ |
null |
tablespace |
string |
表の書込み先の表領域 |
users |
to_nid_column |
string |
宛先ノードの列名 |
dvid |
vertex_id_type |
enum[long, string] |
頂点IDの型 |
long |
注意:
2つの表形式を使用してOracle DatabaseからOracle Big Data Spatial and Graphインメモリー・アナリストにデータを直接読み込むには、次の1つ以上のライセンスが必要です。-
Oracle Big Data Appliance上のOracle Big Data Spatial and Graphライセンス、または
-
サポートされている別の構成上のOracle Big Data Spatial and Graphライセンス、およびOracle Database Enterprise Editionシステム上のOracle Spatial and Graphオプションのライセンス。
Oracle Big Data Spatial and Graphのライセンスの詳細は、『Oracle Big Data Applianceライセンス情報ユーザー・マニュアル』を参照してください。
-
2つの表形式の使用例
-
NULL値の処理方法
2つの表形式の使用例
次の例では、次の表に示す値を使用して、2つのリレーション表(NODESおよびEDGES)からグラフ・データを読み込みます。
表6-4 2つの表の例のノード表値
nid | NP1 | NP2 | NP3 |
---|---|---|---|
1829107 |
“hello” |
06/06/2012 |
0.30 |
1829179 |
“world” |
06/08/2012 |
0.999 |
表6-5 2つの表の例のエッジ表値
eid | from_nid | to_nid | EP1 | EP2 | EP3 |
---|---|---|---|---|---|
21123 |
1829107 |
1829179 |
“alpha” |
06/06/2012 |
10.5 |
48180 |
1788817 |
1829179 |
“beta” |
06/08/2012 |
22.3 |
{
"jdbc_url": "jdbc:oracle:thin:@mydatabaseserver:1521/dbName",
"format": "two_tables",
"datastore": "rdbms",
"username": "dbUser",
"password": "dbPassword",
"nodes_table_name": "nodes",
"edges_table_name": "edges",
"node_props": [{
"name": "NP1",
"type": "string"
},{
"name": "NP2",
"type": "date"
},{
"name": "NP3",
"type": "double"
}],
"edge_props": [{
"name": "EP1",
"type": "string"
},{
"name": "EP2",
"type": "date"
},{
"name": "EP3",
"type": "float"
}]
}
2つの表形式の使用の追加例については、「インメモリー・アナリストを使用したApache Spark内のグラフ・データの分析」を参照してください。
NULL値の処理方法
インメモリー・アナリストの場合、ノードまたはエッジ内のプロパティ値をnullにすることはできません。このため、ノードまたはエッジ表内のプロパティ値がnullに設定されている場合は常に、代わりにデフォルト値が割り当てられます。config
オブジェクトに指定されていない場合、デフォルト値はプロパティ・タイプのJavaデフォルト値です(たとえば、double
に対する0.0など)。
ただし、次の例に示すように、config
オブジェクトに異なるデフォルト値を指定することもできます。
{
"name": "NP1",
"type": "double",
"default": 1.0
}
親トピック: インメモリー・アナリスト(PGX)の使用
6.17 インメモリー・アナリストを使用したApache Spark内のグラフ・データの分析
Oracle Big Data Spatial and Graphのプロパティ・グラフ機能を使用すると、インメモリー分析とApache Sparkを統合できます。
次の例では、Sparkコンテキストを作成し、2つの表形式のグラフ(頂点/ノード表およびエッジ表)をSpark DataFrameとしてロードし、このDataFrameからインメモリー・アナリストに読み込み、最後にインメモリー・グラフを作成します。簡単にするために、Java APIのみについて説明します。
(2つの表形式の詳細は、「Oracleの2つの表リレーショナル形式の使用」を参照してください。)
例6-6 Sparkコンテキストの作成
// import classes required by Apache Spark and PGX
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.*;
import oracle.pgx.api.*;
import org.apache.spark.sql.*;
import org.apache.spark.sql.types.*;
String sparkMaster = "spark://..."; // the access point for your Spark cluster
String sparkAppName = "My Spark App ..."; // the name of this application
String [] appJarPaths = new String[] {"/your/jar/path" }; // a file path to your jar file
// create a Spark configuration and a context
SparkConf sparkConf = new SparkConf().setMaster(sparkMaster).setAppName(sparkAppName).setJars(appJarPaths);
JavaSparkContext sc = new JavaSparkContext(sparkConf);
SQLContext sqlContext = new SQLContext(sc);
例6-7 2つの表形式のグラフからのSpark DataFrameの作成
この例では、頂点CSVファイル("頂点表")の各行にlong integer型のID、integer型のVProp1、およびdouble型のVProf2が含まれることを前提としています。また、エッジCSVファイル("エッジ表")の各行にlong integer型のSRCID、long integer型のDSTID、integer型のEProp1、およびdouble型のEProp2が含まれることを前提としています。
JavaRDD<String> vLines = sc.textFile("<path>/test_graph_nodes_table.csv", 2)
JavaRDD<String> eLines = sc.textFile("<path>/test_graph_edges_table.csv", 2)
JavaRDD<Row> vRowRdd = vLines.map(_.split(",")).map(p=>Row(p(0).toLong,p(1).toInt,p(2).toDouble));
StructType vDataframeScheme = new StructType().add("ID", LongType).add("VProp1", IntegerType).add("VProp2", DoubleType);
Dataframe vDataframe = sqlc.createDataFrame(vRowRdd, vDataframeScheme);
JavaRDD<Row> eRowRdd = eLines.map(_.split(",")).map(p=>Row(p(0).toLong,p(1).toLong,p(2).toInt,p(3).toDouble));
StructType eDataframeScheme = new StructType().add("SRCID", LongType).add("DSTID", LongType).add("EProp1", IntegerType).add("EProp2", DoubleType);
Dataframe eDataframe = sqlc.createDataFrame(eRowRdd, eDataframeScheme);
例6-8 インメモリー・アナリストへのSpark DataFrameの読込み(1)
この例では、PgxSession
およびPgxSparkContext
を作成し、PgxSparkContext
を使用して2つのSpark DataFrameからインメモリー・グラフを読み込んで作成します。
String pgxServer = "http://..."; // the access point for a PGX server
// create a PGX session and a context
PgxSession pgxSession = Pgx.getInstance(pgxServer).createSession("spark-session");
PgxSparkContext pgxContext = new PgxSparkContext(sparkContext, pgxSession);
// load into PGX
PgxGraph g = pgxContext.read(vDataframe, eDataframe, "spark-test-graph");
PgxGraph
のインスタンスが作成された後、既存のすべての分析機能を使用できます。
例6-9 インメモリー・アナリストへのSpark DataFrameの読込み(2)
次の例では、2つのSpark DataFrameのペアを作成することにより、すでにロードされているインメモリー・グループg
をApache Sparkに格納し戻します。ペアの要素により、頂点情報とエッジ情報がそれぞれ格納されます。
// store graph "spark-test-graph" into Apache Spark
Pair<DataFrame, DataFrame> dataframePair = pgxContext.writeToDataframes(vertexDataFrame, eDataframeScheme, "spark-test-graph");
6.17.1 Apache Spark内の並列度の制御
Apache Sparkでのグラフ読込みジョブの並列度は、頂点およびエッジRDD/DataFrameオブジェクトのパーティションの数によって決まります。頂点およびエッジRDD/DataFrameオブジェクトのパーティションの合計数がApache Sparkクラスタ内で使用可能なワーカーの合計数より多い場合、PgxSparkContext::read
関数によって例外がスローされます。
この状況では、RDD/DataFrameオブジェクトのパーティションの数を削減することにより、並列度を調整する必要があります。coalesce
APIを使用できます。
たとえば、Sparkクラスタ内に使用可能なワーカーが15あり、インメモリー・アナリストに読み込むグラフに500,000の頂点と1,000,000 (100万)のエッジがあるとします。ワーカーの数が15だとすると、頂点およびエッジ・データ・フレームのパーティションの合計が15を超えないようにする必要があります。そうでない場合、クラスタ内で有効な並列度を超える並列度を要求することになります。
エッジの数が頂点の数の2倍あるため、使用可能なワーカーの1/3 (3分の1)を頂点に割り当て、2/3 (3分の2)をエッジに割り当てることをお薦めします。このような比率で15のワーカーをすべて使用するには、5つの頂点パーティションと10のエッジ・パーティションを作成します。次に例を示します。
var newVertexDataFrame = vertexDataFrame.coalesce(5);
var newEdgeDataFrame = edgeDataFrame.coalesce(10);
6.18 インメモリー・アナリストZeppelinインタプリタの使用
インメモリー・アナリストには、Apache Zeppelinのインタプリタ実装が用意されています。このチュートリアルのトピックでは、ローカルのZeppelinインストールにインメモリー・アナリスト・インタプリタをインストールし、いくつかの簡単な操作を実行する方法について説明します。
インタプリタのインストール
次の手順はZeppelinバージョン0.7.0を使用してテストしたものであり、これよりバージョンが新しい場合は変更する必要がある場合があります。
-
Apache Zeppelinのダウンロードおよびインストールがまだ完了していない場合は、これらを実行します。
-
インメモリー・アナリスト・インタプリタのパッケージを見つけます: /opt/oracle/oracle-spatial-graph/property_graph/pgx/client/pgx-<version>-zeppelin-interpreter.zip
-
公式のインタプリタのインストール手順に従います。
-
インメモリー・アナリスト・インタプリタのパッケージを
$ZEPPELIN_HOME/interpreter/pgx
に解凍します。 -
$ZEPPELIN_HOME/conf/zeppelin-site.xml
を編集し、インメモリー・アナリストZeppelinインタプリタ・クラスnameoracle.pgx.zeppelin.PgxInterpreter
をzeppelin.interpreters
プロパティ・フィールドに追加します。 -
次のステップ(Zeppelinの再起動)の前に、CLASSPATH設定を消去します。Linuxシステムでは、シェルで
unset CLASSPATH
を実行します。 -
Zeppelinを再起動します。
-
Zeppelinインタプリタ・ページで、「+Create」ボタンをクリックし、インタプリタ・グループ
pgx
の新しいインタプリタを追加します。
-
-
新しいインメモリー・アナリスト・インタプリタを構成します。
-
「interpreter for note」のオプションを選択します。
-
Shared: すべてのノートが同じインメモリー・アナリスト・セッションを共有します(非推奨)。
-
Scoped: すべてのノートが独自のインメモリー・アナリスト・セッションを取得しますが、同じプロセスを共有します(推奨)。
-
Isolated: すべてのノートが独自のインメモリー・クライアント・シェル・プロセスを取得します。これが最高の分離レベルですが、Zeppelinインタプリタを実行しているシステム上で不要なリリースが消費される可能性があります。
-
-
pgx.baseUrlについては、インメモリー・アナリスト・インタプリタがリモートのインメモリー・アナリスト・サーバーと通信するクライアントのように機能するため、インメモリー・アナリスト・サーバーが実行されているベースURLを少なくとも指定する必要があります。
-
インタプリタの使用
インメモリー・アナリスト・インタプリタにpgx
という名前を付けた場合、他の任意のインタプリタの場合と同じように、パラグラフの先頭を%pgx
ディレクティブにすることにより、パラグラフをインメモリー・アナリスト・インタプリタに送信できます。
インメモリー・アナリストZeppelinインタプリタは、インメモリー・アナリストと同じ方法でパラグラフを評価し、出力を返します。したがって、次の例のように、任意の有効なインメモリー・アナリスト・シェル・スクリプトがインメモリー・アナリスト・インタプリタ内で動作します。
%pgx
g_brands = session.readGraphWithProperties("/opt/data/exommerce/brand_cat.json")
g_brands.getNumVertices()
rank = analyst.pagerank(g_brands, 0.001, 0.85, 100)
rank.getTopKValues(10)
次の図は、その問合せのアイコンをクリックして実行した後の結果を示します。
この図から分かるように、インメモリー・アナリストZeppelinインタプリタは、rank.getTopKValues(10)
から返された値をZeppelin表としてレンダリングすることにより、結果をより便利に閲覧しやすくします。
プロパティ値(getTopKValues()、getBottomKValues()およびgetValues()
)以外にも、次の戻り型がパラグラフから返される場合、これらも表として自動的にレンダリングされます。
-
PgqlResultSet
-PgxGraph
クラスのqueryPgql("...")
メソッドから返されるオブジェクト -
MapIterable
-PgxMap
クラスのentries()
メソッドから返されるオブジェクト
他のすべての戻り型およびエラーは、インメモリー・アナリスト・シェルによる場合と同じように、標準の文字列として返されます。
Zeppelinの詳細は、公式のZeppelinドキュメントを参照してください。
親トピック: インメモリー・アナリスト(PGX)の使用
6.19 インメモリー・アナリスト・エンタープライズ・スケジューラの使用
インメモリー・アナリスト・エンタープライズ・スケジューラには、高度なスケジューリング機能が用意されています。
注意:
高度なスケジューリング機能は現在、Linux (x86_64)、Mac OS X (x86_64)およびSolaris (x86_64、SPARC)に対してのみ使用可能です。
このチュートリアルのトピックでは、インメモリー・アナリスト・エンタープライズ・スケジューラの高度なスケジューリング機能を使用する方法を示します。次について説明します。
-
インメモリー・アナリスト・サーバーの構成による高度なスケジューリング機能の有効化方法
-
実行環境の取得および検査方法
-
実行環境の変更方法および実行環境でのタスクの実行方法
高度なスケジューリング機能の有効化
高度なスケジューリング機能を有効にするには、インメモリー・アナリスト・インスタンス構成のフラグallow_override_scheduling_information
をtrue
に設定します。
{ "allow_override_scheduling_information": true }
実行環境の取得および検査
実行環境はセッションにバインドされています。セッションの実行環境を取得するには、PgxSession
に対してgetExecutionEnvironment()
を呼び出します。
pgx> execEnv = session.getExecutionEnvironment() ==> ExecutionEnvironment[session=576af1fd-73aa-4866-abf0-00a71757d75b]
実行環境は、3つのサブ環境(タスク・タイプごとに1つ)に分割されます。
-
IO環境: IOタスク用
-
分析環境: CPUバウンドの分析タスク用
-
高速分析環境: 軽量だがCPUバウンドの分析タスク用
実行環境の現在の状態を問い合せるには、getValues()
メソッドを呼び出します。
pgx> execEnv.getValues() ==> io-pool.num_threads_per_task=72 ==> analysis-pool.max_num_threads=72 ==> analysis-pool.weight=72 ==> analysis-pool.priority=MEDIUM ==> fast-track-analysis-pool.max_num_threads=72 ==> fast-track-analysis-pool.weight=1 ==> fast-track-analysis-pool.priority=HIGH
サブ環境を取得するには、getIoEnvironment()
、getAnalysisEnvironment()
およびgetFastAnalysisEnvironment()
メソッドを使用します。各サブ環境には、サブ環境の構成を取得するために独自のgetValues()
メソッドが用意されています。
pgx> ioEnv = execEnv.getIoEnvironment() ==> IoEnvironment[pool=io-pool] pgx> ioEnv.getValues() ==> num_threads_per_task=72 pgx> analysisEnv = execEnv.getAnalysisEnvironment() ==> CpuEnvironment[pool=analysis-pool] pgx> analysisEnv.getValues() ==> max_num_threads=72 ==> weight=72 ==> priority=MEDIUM pgx> fastAnalysisEnv = execEnv.getFastAnalysisEnvironment() ==> CpuEnvironment[pool=fast-track-analysis-pool] pgx> fastAnalysisEnv.getValues() ==> max_num_threads=72 ==> weight=1 ==> priority=HIGH
実行環境の変更および更新済環境でのタスクの発行
IoEnvironment
のsetNumThreadsPerTask()
メソッドを使用することにより、I/O環境のスレッドの数を変更できます。この値は即時更新され、更新後に発行されたタスクはすべて、更新された値を使用して実行されます。
pgx> ioEnv.setNumThreadsPerTask(8) ==> 8 pgx> g = session.readGraphWithProperties(...) ==> PgxGraph[name=graph,N=3,E=6,created=0]
環境を初期値にリセットするには、reset()
メソッドを呼び出します。
pgx> ioEnv.reset() ==> null
CPU環境の場合、setWeight()、setPriority()およびsetMaxThreads()メソッドを使用してスレッドの重み、優先度および最大数を変更できます。
pgx> analysisEnv.setWeight(50) ==> 50 pgx> fastAnalysisEnv.setMaxThreads(1) ==> 1 pgx> rank = analyst.pagerank(g) ==> VertexProperty[name=pagerank,type=double,graph=graph]
ExecutionEnvironment
に対してreset()
を呼び出すと、すべての環境を一度にリセットできます。
pgx> execEnv.reset() ==> null
6.19.1 実行環境でのラムダ構文の使用
ラムダ構文を使用して、実行環境で使用する手順を結合できます。通常、この環境は次の方法で使用されます。
-
実行環境の設定
-
タスクの実行
-
実行環境のリセット
これらの手順を簡単にするために、これら3つの手順を結合するためのメソッドが用意されています。setメソッドごとに、更新された値をとるwith接頭辞および更新された値を使用して実行する必要があるラムダを使用するメソッドがあります。たとえば、setNumThreadsPerTask()の代わりに、次のように呼び出すことができるwithNumThreadsPerTask()と呼ばれるメソッドがあります。
-
JavaアプリケーションでJava 8ラムダを使用する場合:
import oracle.pgx.api.*; import oracle.pgx.api.executionenvironment.*; PgxGraph g = ioEnv.withNumThreadsPerTask(8, () -> session.readGraphWithPropertiesAsync(...));
-
インメモリー・アナリスト・シェルでGroovyのクロージャを使用する場合:
pgx> g = ioEnv.withNumThreadsPerTask(8, { session.readGraphWithPropertiesAsync(...) } ) ==> PgxGraph[name=graph,N=3,E=6,created=0]
これらは両方とも、次の空き指定のシーケンスと等価です。
oldValue = ioEnv.getNumThreadsPerTask() ioEnv.setNumThreadsPerTask(currentValue) g = session.readGraphWithProperties(...) ioEnv.setNumThreadsPerTask( oldValue )