6 インメモリー・アナリスト(PGX)の使用

Oracle Spatial and Graphのインメモリー・アナリスト機能は、一連の分析機能をサポートしています。

この章では、インメモリー・アナリストを使用する例について説明します(プロパティ・グラフ・インメモリー分析とも呼ばれ、Javadoc、コマンドライン、パスの説明、エラー・メッセージなどではPGXと省略されます)。主なトピックは次のとおりです。

6.1 グラフのメモリーへの読込み

このトピックでは、シェル・インタフェースを使用したメモリーへの対話によるグラフの読込みの例について説明します。

主な手順は次のとおりです。

6.1.1 インメモリー・アナリスト・サーバー・インスタンスへの接続

インメモリー・アナリストを起動する手順:

  1. プロパティ・グラフのサポートがインストールされているシステムで端末セッションを開始します。
  2. シェルでは、次のコマンドを入力しますが、開始コマンド、または必要なインスタンスのタイプへの接続コマンドのいずれか一方を選択します。
    cd $PGX_HOME
    ./bin/pgx --help
    ./bin/pgx --version
     
    # start embedded shell
    ./bin/pgx
     
    # start remote shell
    ./bin/pgx --base_url http://my-server.com:8080/pgx

    埋込みシェルの場合、出力は次のようになります。

    10:43:46,666 [main] INFO Ctrl$2 - >>> PGX engine running.
    pgx>
  3. オプションで、事前定義されている変数も表示します。
    pgx> instance
    ==> ServerInstance[embedded=true]
    pgx> session
    ==> PgxSession[ID=ab9bdc1d-3401-460c-b1cf-5ef97ec5c5f9,source=pgxShell]
    pgx> analyst
    ==> NamedArgumentAnalyst[session=ab9bdc1d-3401-460c-b1cf-5ef97ec5c5f9]
    pgx>
    

    その他のトピックの例では、インスタンスおよびセッション変数は、ここで示すとおり設定されるとみなされます。

インメモリー・アナリスト・ソフトウェアが正しくインストールされている場合、エンジン実行ログ・メッセージとインメモリー・アナリスト・シェル・プロンプト(pgx>)が表示されます。

変数instancesession、およびanalystが使用可能です。

このトピックの前の例では、pgxコマンドでリモートURLを指定していないため、シェルがローカル・インスタンスを開始します。

6.1.2 シェル・ヘルプの使用

インメモリー・アナリスト・シェルには、:helpコマンドを使用してアクセスできるヘルプ・システムが用意されています。

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 sample.adjデータからレンダリングされたプロパティ・グラフ

図6-1の説明が続きます
「図6-1 sample.adjデータからレンダリングされたプロパティ・グラフ」の説明

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
});

次のトピックでは、プロパティ・グラフをメモリーに読み込むその他の例について説明します。

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つのエッジがあり、各エッジは互いの反対の方向を指し示しています。)

図6-2 単純なカスタム・プロパティ・グラフ

図6-2の説明が続きます
「図6-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は、グラフ内のそれぞれの頂点(ノード)について、01の間のランク値を計算し、その値を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部サブグラフを作成できます。

グラフのメモリーへの読込みについては、「グラフ・データのメモリーへの読込み」を参照してください。

6.6.1 フィルタ式について

フィルタ式は、各頂点または各エッジで評価される式です。式によって、結果(この場合はサブグラフ)に含まれるようにエッジを完成させる述部を定義できます。

4つの頂点(ノード)と4つのエッジで構成される図6-1のグラフを検討します。フィルタ式src.prop1 == 10と一致するエッジについては、元の頂点のpropプロパティが10になります。図6-3に示すフィルタ式と一致する2つのエッジ。

図6-3 サンプル・グラフ

図6-3の説明が続きます
「図6-3 サンプル・グラフ」の説明

次のエッジ・フィルタ式は、

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を持つ頂点)が含まれます。

図6-4 簡易エッジ・フィルタで作成されたサブグラフ

図6-4の説明が続きます
「図6-4 簡易エッジ・フィルタで作成されたサブグラフ」の説明

次の頂点フィルタ式は、

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-5 outDegreeフィルタと一致するエッジ

図6-5の説明が続きます
「図6-5 outDegreeフィルタと一致するエッジ」の説明

図6-6はフィルタを適用した結果のグラフを示します。フィルタは頂点99と1908に対応するエッジを除外するため、その頂点も除外します。

図6-6 outDegreeフィルタで作成されたグラフ

図6-6の説明が続きます
「図6-6 outDegreeフィルタで作成されたグラフ」の説明

6.6.5 式フィルタの結合

頂点フィルタをエッジ・フィルタと結合できます。

両方のフィルタが個別に評価され、後で次のいずれかを作成することによってマージされます。

  • 結果の結合

  • 結果の交差

2つのフィルタの結合の作成

結合の実行対象としてエッジ・フィルタと、

src.prop1 == 10

頂点フィルタを選択すると、

vertex.prop1 < 10

次のグラフに示す結果が得られます。

図6-7 2つのフィルタの結合

図6-7の説明が続きます
「図6-7 2つのフィルタの結合」の説明

シェルの例:

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つのフィルタの交差の作成

結合の例で説明したフィルタの交差を作成すると、単一の頂点のみで構成された次のグラフが生成されます。

図6-8 2つのフィルタの交差

図6-8の説明が続きます
「図6-8 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);
  });
});

シェル内では、PqglResultSetprintメソッドを使用してテキスト形式で結果セットを適切に印刷できます。

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")

この問合せでは、次の処理を実行します。

  1. `collaborates'エッジ・ラベルを照合することにより、グラフから協力関係パターンをすべて見つけます。

  2. 見つかったパターンをソース頂点別にグループ化します。

  3. 各グループにカウント集計を適用し、協力者の数を見つけます。

  4. 協力者の数別に降順でグループに順序を付けます。

  5. 最初の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 例: 電気装置間の推移的な接続性

この例では、頂点間で到達可能性をテストします。ここでは、次の図の電気ネットワークのグラフを使用します。

図6-9 電気ネットワークのグラフ

図6-9の説明が続きます
「図6-9 電気ネットワークのグラフ」の説明

この例では、グラフ内のすべての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を構成する必要があります。

  1. インメモリー・アナリストのWebアプリケーション・アーカイブ(WAR)ファイルをJettyのwebappsディレクトリにコピーします(<VERSION>を実際のバージョン番号に置き換えます)。

    cp $PGX_HOME/server/shared-mem/pgx-webapp-<VERSION>.war.war $JETTY_HOME/webapps/pgx.war
  2. ポート8080が未使用であることを確認し、Jettyを開始します。

    cd $JETTY_HOME
    java -jar start.jar
    
  3. Jettyが動作していることを確認します。

    cd $PGX_HOME
    ./bin/pgx --base_url http://localhost:8080/pgx
    
  4. (オプション)インメモリー・アナリスト構成ファイルを変更します。

    インメモリー・アナリスト・エンジンの構成ファイル(pgx.conf)およびロギング・パラメータ(log4j.xml)は、WEB-INF/classesのWARファイル内にあります。

    変更を行った後、サーバーを再起動して変更を有効にします。

関連項目:

http://eclipse.org/jetty/documentation/にある構成および使用に関するJettyドキュメント

6.10 Apache Tomcatへのデプロイ

インメモリー・アナリストは、Eclipse Jetty、Apache Tomcat、またはOracle WebLogicにデプロイできます。この例では、Webアプリケーションとしてインメモリー・アナリストをApache Tomcatにデプロイする方法を示しています。

注意:

これらの手順は、インメモリー・アナリストのテストのみを目的としています。本格的なデプロイメントの場合、正しい認証および認可を適用し、資格情報を安全に格納し、HTTPSを介して接続のみを許可するよう、Apache Tomcatを構成する必要があります。

  1. インメモリー・アナリストWARファイルをwebappsディレクトリにコピーします。次に例を示します(および<VERSION>を実際のバージョン番号に置き換えます):
    cp $PGX_HOME/server/shared-mem/pgx-webapp-<VERSION>.war $CATALINA_HOME/webapps/pgx.war
    
  2. ポート8080が未使用であることを確認し、Tomcatを起動します。
    cd $CATALINA_HOME
    ./bin/startup.sh
  3. Tomcatが動作していることを確認します。
    cd $PGX_HOME
    ./bin/pgx --base_url http://localhost:8080/pgx
    

関連項目:

Tomcatのドキュメントは、次を参照してください

http://tomcat.apache.org/tomcat-7.0-doc/

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

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

6.11.3 サーバーが動作していることの確認

サーバーに接続できることを確認します。

$PGX_HOME/bin/pgx --base_url http://localhost:7001/pgx

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.trustStorejavax.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つのモード(コンピュータ)が割り当てられており、これらがホスト名hostname0hostname1hostname2および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
}

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にコピーし、それをメモリーに読み込みます。

  1. グラフ・データをHDFSにコピーします。

    cd $PGX_HOME
    hadoop fs -mkdir -p /user/pgx
    hadoop fs -copyFromLocal ../examples/pgx/graphs/sample.adj /user/pgx
    
  2. グラフ構成ファイルsample.adj.jsonuriフィールドを、HDFSリソースを指し示すように編集します。

    {
      "uri": "hdfs:/user/pgx/sample.adj", 
      "format": "adj_list",
      "node_props": [{ 
        "name": "prop", 
        "type": "integer" 
      }],
      "edge_props": [{ 
        "name": "cost", 
        "type": "double" 
      }],
      "separator": " "
    }
    
  3. 構成ファイルをHDFSにコピーします。

    cd $PGX_HOME
    hadoop fs -copyFromLocal ../examples/pgx/graphs/sample.adj.json /user/pgx
    
  4. 次の例に示すように、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");

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

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

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_secs0に設定してタイムアウトを無効にすると、インメモリー・アナリスト・サーバーはユーザーまたは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.15.3 インメモリー・アナリスト・サービスの監視

インメモリー・アナリスト・サービスを監視するには、リソース・マネージャWeb UIで対応するYARNアプリケーションをクリックします。デフォルトでは、Web UIは次の場所にあります

http://resource-manager-hostname:8088/cluster

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
}

6.17 インメモリー・アナリストを使用したApache Spark内のグラフ・データの分析

Oracle Big Data Spatial and Graphのプロパティ・グラフ機能を使用すると、インメモリー分析とApache Sparkを統合できます。

次の例では、Sparkコンテキストを作成し、2つの表形式のグラフ(頂点/ノード表およびエッジ表)をSpark DataFrameとしてロードし、このDataFrameからインメモリー・アナリストに読み込み、最後にインメモリー・グラフを作成します。簡単にするために、Java APIのみについて説明します。

(2つの表形式の詳細は、「Oracleの2つの表リレーショナル形式の使用」を参照してください。)

参照: Apache Spark内の並列度の制御

例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を使用してテストしたものであり、これよりバージョンが新しい場合は変更する必要がある場合があります。

  1. Apache Zeppelinのダウンロードおよびインストールがまだ完了していない場合は、これらを実行します。

  2. インメモリー・アナリスト・インタプリタのパッケージを見つけます: /opt/oracle/oracle-spatial-graph/property_graph/pgx/client/pgx-<version>-zeppelin-interpreter.zip

  3. 公式のインタプリタのインストール手順に従います。

    1. インメモリー・アナリスト・インタプリタのパッケージを$ZEPPELIN_HOME/interpreter/pgxに解凍します。

    2. $ZEPPELIN_HOME/conf/zeppelin-site.xmlを編集し、インメモリー・アナリストZeppelinインタプリタ・クラスnameoracle.pgx.zeppelin.PgxInterpreterzeppelin.interpretersプロパティ・フィールドに追加します。

    3. 次のステップ(Zeppelinの再起動)の前に、CLASSPATH設定を消去します。Linuxシステムでは、シェルでunset CLASSPATHを実行します。

    4. Zeppelinを再起動します。

    5. Zeppelinインタプリタ・ページで、「+Create」ボタンをクリックし、インタプリタ・グループpgxの新しいインタプリタを追加します。

  4. 新しいインメモリー・アナリスト・インタプリタを構成します。

    1. 「interpreter for note」のオプションを選択します。

      • Shared: すべてのノートが同じインメモリー・アナリスト・セッションを共有します(非推奨)。

      • Scoped: すべてのノートが独自のインメモリー・アナリスト・セッションを取得しますが、同じプロセスを共有します(推奨)。

      • Isolated: すべてのノートが独自のインメモリー・クライアント・シェル・プロセスを取得します。これが最高の分離レベルですが、Zeppelinインタプリタを実行しているシステム上で不要なリリースが消費される可能性があります。

    2. 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ドキュメントを参照してください。

6.19 インメモリー・アナリスト・エンタープライズ・スケジューラの使用

インメモリー・アナリスト・エンタープライズ・スケジューラには、高度なスケジューリング機能が用意されています。

注意:

高度なスケジューリング機能は現在、Linux (x86_64)、Mac OS X (x86_64)およびSolaris (x86_64、SPARC)に対してのみ使用可能です。

このチュートリアルのトピックでは、インメモリー・アナリスト・エンタープライズ・スケジューラの高度なスケジューリング機能を使用する方法を示します。次について説明します。

  • インメモリー・アナリスト・サーバーの構成による高度なスケジューリング機能の有効化方法

  • 実行環境の取得および検査方法

  • 実行環境の変更方法および実行環境でのタスクの実行方法

高度なスケジューリング機能の有効化

高度なスケジューリング機能を有効にするには、インメモリー・アナリスト・インスタンス構成のフラグallow_override_scheduling_informationtrueに設定します。

{
  "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

実行環境の変更および更新済環境でのタスクの発行

IoEnvironmentsetNumThreadsPerTask()メソッドを使用することにより、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 実行環境でのラムダ構文の使用

ラムダ構文を使用して、実行環境で使用する手順を結合できます。通常、この環境は次の方法で使用されます。

  1. 実行環境の設定

  2. タスクの実行

  3. 実行環境のリセット

これらの手順を簡単にするために、これら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 )