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

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

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

多くの例を実行するには、「グラフ・データのパラレル・ロード」に記載されているように、グラフ・データを最初にロードする必要があります。

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

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

サブトピックでは主なステップを示します。

注意:

セキュアなデプロイメントを行うために、rootユーザーを使用してインメモリー分析サーバーを実行しないでください

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

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

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

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

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

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

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

The variables instance, session, and analyst are ready to use.

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

6.1.2 シェル・ヘルプの使用

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

6.1.3 構成ファイルでのグラフ・メタデータの指定

/opt/oracle/oracle-spatial-graph/property_graph/examples/pgx/graphs/のインストール・ディレクトリにグラフの例が含まれています。ここでは、インメモリー・アナリストがグラフを読み取る方法を説明する構成ファイルを使用します。

opg> 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型のエッジ・プロパティで構成されていることを示します。

これは隣接するリスト形式のグラフ・データです。

opg> 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:)

相対パスは常に、構成ファイルの親ディレクトリに対して相対的に解決されます。

例: シェルを使用したグラフの読取り

opg> 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]
opg> graph.getNumVertices()
==> 4

例: Javaを使用したグラフの読取り

import oracle.pgx.api.*;

ServerInstance instance = Pgx.getInstance(Pgx.EMBEDDED_URL); 
// ServerInstance instance = Pgx.getInstance("http://my-server2: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");

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

注意:

多くの例を実行するには、「グラフ・データのパラレル・ロード」に記載されているように、グラフ・データを最初にロードする必要があります。

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がメモリーに読み込まれます。

opg> 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)を元のデータから生成し、三角形の数をカウントします。

opg> g = session.readGraphWithProperties("/tmp/my_graph_nosql.json", "connections")
opg> analyst.countTriangles(g, false)
==> 8
6.1.4.3 ローカル・ファイル・システムに格納されているグラフのメモリーへの読込み

次のコマンドでは、構成ファイルでのグラフ・メタデータの指定の構成ファイルおよびmy-graphという名前を使用します。

opg> 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

クライアント/サーバー・モードでのローカル・ファイル・システムからのロードを可能にします。デフォルトはfalseです。trueに設定する場合、ディレクトリをリストするプロパティdatasource_dir_whitelistを追加で指定します。サーバーは、ホワイトリストに記載されているディレクトリからのみ読み取ることができます。

false

allow_override_scheduling_information

boolean

Trueの場合、タスク重み、タスク優先度、スレッド数などのスケジューリング情報のオーバーライドをすべてのユーザーに許可します

true

allowed_remote_loading_locations stringの配列

リモートの場所からPGXエンジンへのグラフのロードを許可します(http、https、ftp、ftps、s3、hdfs)。デフォルトは空です。サポートされる値は"*" (アスタリスク)です。これは、すべてのリモートの場所が許可されることを意味します。事前ロードされるグラフは、この設定の値に関係なく任意の場所からロードされることに注意してください。警告: * (アスタリスク)を指定するのは、PGXリモート・インタフェースのユーザーがローカル・ファイル・システム上のファイルにアクセスするのを明示的に許可する場合のみにする必要があります。

[]

allow_task_timeout_overwrite

boolean

trueの場合、セッションによってデフォルトのタスク・タイムアウトを上書きできます

true

allow_user_auto_refresh

boolean

trueの場合、ユーザーがロードするグラフを自動リフレッシュできます。falseの場合、preload_graphsに記述されているグラフのみに対して自動リフレッシュを有効にできます。

false

allowed_remote_loading_locations stringの配列 (このオプションを使用するとセキュリティが低下する可能性があるため、作業の内容を把握している場合のみ使用してください。)リモートの場所からPGXエンジンへのグラフのロードを許可します(http、https、ftp、ftps、s3、hdfs)。空の場合は、デフォルトの場合と同様に、リモートの場所は許可されません。配列で"*"を指定すると、すべてのリモートの場所が許可されます。値"*"のみが現在サポートされています。事前ロードされるグラフは、この設定の値に関係なく任意の場所からロードされることに注意してください。 []
basic_scheduler_config object 分岐結合プール・バックエンドの構成パラメータ。 null

bfs_iterate_que_task_size

integer

BFS反復QUEフェーズのタスク・サイズ。

128

bfs_threshold_parent_read_based

number

BFSトラバース・レベル・アイテムを親読取りベースのアクセス戦略に切り替える際のしきい値。

0.05

bfs_threshold_read_based

integer

BFSトラバース・レベル・アイテムを読取りベースのアクセス戦略に切り替える際のしきい値。

1024

bfs_threshold_single_threaded

integer

BFSトラバース・レベル・アイテムの頂点が単一スレッドでアクセスされる数のしきい値。

128

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

datasource_dir_whitelist stringの配列 allow_local_filesystemが設定されている場合は、ファイルの読取りが許可されているディレクトリのリスト。 []

dfs_threshold_large

integer

DFS実装が多数の頂点に対して最適化されたデータ構造に切り替わるまでにどれくらいの数の頂点がアクセスされる必要があるかを決める値。

4096

enable_csrf_token_checks

boolean

trueの場合、PGX Webアプリケーションは、クライアントから送信された要求パラメータとクロスサイト・リクエスト・フォージェリ(CSRF)トークンCookieが存在して一致するかどうかを検証します。これは、CSRF攻撃を防止することが目的です。

true

enable_gm_compiler

boolean

[solaris studioを使用してプロファイリングする場合に関連]有効である場合、'er_label'コマンドを使用して試験にラベルが付けられます。

false

enable_shutdown_cleanup_hook

boolean

trueの場合、PGXはJVMのシャットダウン時にPGXを自動的にシャットダウンするJVMシャットダウン・フックを追加します。通知:シャットダウン・フックを非アクティブにし、PGXを明示的にシャットダウンしない場合、一時ディレクトリの汚染につながる可能性があります。

true

enterprise_scheduler_config

object

エンタープライズ・スケジューラの構成パラメータ。

null

enterprise_scheduler_flags

object

[enterprise_schedulerに関連]  エンタープライズ・スケジューラ固有の設定。

null

explicit_spin_locks

boolean

trueは、ロックが使用可能になるまでループ内で明示的にスピンすることを意味します。falseは、コンテキストを切り替えるかスピンするかを決定するためにJVMに依存するJDKロック・キーを使用することを意味します。通常、この値をtrueに設定した方がパフォーマンスが向上します。

true

graph_algorithm_language enum[GM_LEGACY, GM, JAVA] 使用するフロントエンド・コンパイラ。 gm
graph_validation_lever enum[low, high] 新しくロードまたは作成されたグラフで実行される検証のレベル。 low
ignore_incompatible_backend_operations boolean trueの場合、RTSまたはFJプールで互換性のない操作および構成値を検出した場合のみログに記録します。falseの場合、例外がスローされます。 false
in_place_update_consistency enum[ALLLOW_INCONSISTENCIES, CANCEL_TASKS] インプレース更新の実行時に使用される一貫性モデル。インプレース更新が有効な場合のみ該当します。現時点では、更新が構造的でない場合、更新はインプレースでのみ適用されます(プロパティのみを変更)。現在2つのモデルが実装されており、1つのモデルは更新の実行時に新しいタスクのみが遅延し、もう1つのモデルでは実行中のタスクも遅延します。 allow_inconsistencies
init_pgql_on_startup boolean trueの場合、PGQLはPGXの起動時に直接初期化されます。そうでない場合、PGQLの初回使用時に初期化されます。 true
interval_to_poll_max integer 1回到達すると、ジョブ・ステータスのポーリング間隔が固定される、指数バックオフの上限(ミリ秒)。 1000
java_home_dir string Javaのホーム・ディレクトリへのパス。<system-java-home-dir>に設定した場合は、java.homeシステム・プロパティを使用します。 null
large_array_threshold integer 配列のサイズが大きすぎて通常のJava配列を使用できない場合のしきい値。これは使用しているJVMによって異なります。(デフォルトはInteger.MAX_VALUE - 3です) 2147483644

max_active_sessions

integer

一度に有効することが許可されたセッションの最大数。

1024

max_distinct_strings_per_pool integer [string_pooling_strategyが索引付けされている場合のみ該当]超えた場合にプーリングを停止する、プロパティごとの個別の文字列の数。制限に達すると、例外がスローされます。 65536

max_off_heap_size

integer

OutOfMemoryErrorがスローされるまでにPGXが割り当てることが許可されたオフピーク・メモリーの最大量(メガバイト単位)。注意: この制限は、丸めおよび同期のトレードオフのため、絶対に超えないことが保証されるわけではありません。これは、PGXが新しいメモリー割当て要求を拒否し始めた際のしきい値としてのみ機能します。

<使用可能な物理メモリー>

max_queue_size_per_session

integer

セッションごとにキューに入れておくことが許可された保留タスクの最大数。セッションが最大に達すると、新しく受け取ったそのセッションの要求が拒否されます。マイナスの値は、制限がないことを意味します。

-1

max_snapshot_count

integer

同時にエンジンにロードすることが可能なスナップショットの数。新しいスナップショットは、自動更新または強制更新を介して作成できます。グラフのスナップショットの数がこのしきい値に達した場合、これ以上の自動更新は実行されなくなり、1つ以上のスナップショットがメモリーから削除されるまでは、強制更新を実行すると例外が発生します。値がゼロの場合、無制限の数のスナップショットをサポートすることを示します。

0

memory_allocator enum[basic_allocator, enterprise_allocator] 使用するメモリー・アロケータ。 basic_allocator

memory_cleanup_interval

integer

メモリーのクリーンアップ間隔(秒単位)。

600

ms_bfs_frontier_type_strategy

enum[auto_grow, short, int]

MS-BFSフロンティアに使用するタイプの戦略。

auto_grow

num_spin_locks

integer

生成された各アプリケーションがインストールを作成するスピン・ロックの数。トレードオフ: 数が小さい場合、メモリーの消費量が小さいことを意味し、数が大きい場合、実行処理が速くなることを意味します(アルゴリズムにスピン・ロックが使用されている場合)。

1024

parallelism integer スレッド・プールで使用されるワーカー・スレッド数。注意:呼出し元のスレッドが別のスレッド・プールの一部である場合、この値は無視され、親プールの並列度が使用されます。 <CPUの数>
pattern_matching_supernode_cache_threshold integer スーパーノードになるノードの近傍の最小数。これはパターン一致エンジン用です。 1000
pooling_factor number [string_pooling_strategyがon_heapの場合のみ該当] この値は、文字列プールがプロパティ・サイズと同じ大きさになり、プーリングが無効になる可能性を防ぎます。 0.25

preload_graphs

オブジェクトの配列

起動時に登録されるグラフ構成のリスト。各アイテムには、グラフ構成へのパス、グラフの名前、およびグラフを公開するかどうかが含まれます。

[]

random_generator_strategy enum[non_deterministic, deterministic] PGXで乱数を生成する方法。 non_deterministic

random_seed

long

[deterministicランダム数ジェネレータのみに関連]インメモリー・アナリストで使用されるdeterministicランダム数ジェネレータのシード。デフォルトは-24466691093057031です。

-24466691093057031

release_memory_threshold

double

エンジンが未使用のグラフを解放するまでの使用済メモリーのしきい値パーセンテージ(小数)。例: 値が0.0である場合、グラフは参照数がゼロになると同時に解放されることを意味します。つまり、そのグラフをロードしたすべてのセッションが破棄されます/タイムアウトします。値が1.0である場合、グラフは一切解放されず、メモリーに収まらないグラフが必要になると同時にOutOfMemoryErrorsがスローされます。値が0.7である場合、メモリー内のグラフを現在使用しているセッションがない場合でも、メモリー消費量の合計が使用可能なメモリー合計の70%を下回っている限り、これらのグラフがすべて保持されます。消費量が70%を超えているときに別のグラフをロードする必要がある場合、メモリー消費量が再度70%を下回るまで未使用のグラフが解放されます。

0.85

revisit_threshold integer 到達するノードからの一致する結果の最大数。 4096
scheduler enum[basic_scheduler, enterprise_scheduler] 使用するスケジューラ。basic_schedulerは、基本機能を備えたスケジューラを使用します。enterprise_schedulerは、複数のタスクを同時に実行してパフォーマンスを改善するための拡張エンタープライズ機能を備えたスケジューラを使用します。 advanced_scheduler

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

string_pooling_strategy enum[indexed, on_heap, none] [use_string_poolが有効な場合のみ該当] 使用する文字列プーリング戦略。 on_heap

task_length

integer

デフォルトのタスクの長さ(タスク・スティーリング戦略の場合のみ関連)。100から10000にする必要があります。トレードオフ: 数が小さい場合、よりファイングレインなタスクが生成され、スティーリングのスループットが高くなります。数が大きい場合、メモリー消費量およびGCアクティビティが小さくなります。

4096

tmp_dir

string

コンパイル・アーティファクトおよび他の一時データを格納するための一時ディレクトリ。<system-tmp-dir>に設定されている場合、基礎となるシステムの標準tmpディレクトリ(Linuxの場合は/tmp)を使用します。

<system-tmp-dir>

udf_config_directory

string

UDFファイルを含むディレクトリ・パス。

null

use_memory_mapper_for_reading_pgb boolean trueの場合、可能な場合はPGB形式でグラフを読み取るためのメモリー・マップ・ファイルを使用してください。falseの場合は、常にストリームベースの実装を使用してください。 true
use_memory_mapper_for_storing_pgb boolean trueの場合、可能な場合はPGB形式でグラフを格納するためのメモリー・マップ・ファイルを使用してください。falseの場合は、常にストリームベースの実装を使用してください。 true

エンタープライズ・スケジューラのパラメータ

次のパラメータは、高度なスケジューラが使用されている場合にのみ該当します。(基本スケジューラを使用している場合は無視されます)。

  • analysis_task_config

    分析タスクの構成。型: object。デフォルト: prioritymediummax_threads<CPUの数>weight<CPUの数>

  • fast_analysis_task_config

    高速分析タスクの構成。型: object。デフォルト: priorityhighmax_threads<CPUの数>weight1

  • maxnum_concurrent_io_tasks

    同時タスクの最大数。型: integer。デフォルト: 3

  • num_io_threads_per_task

    高速分析タスクの構成。型: object。デフォルト: <CPUの数>

基本スケジューラのパラメータ

次のパラメータは、基本スケジューラが使用されている場合にのみ該当します。(高度なスケジューラを使用している場合は無視されます)。

  • num_workers_analysis

    分析タスクに使用するワーカー・スレッドの数。型: integer。デフォルト: <CPUの数>

  • num_workers_fast_track_analysis

    高速分析タスクに使用するワーカー・スレッドの数。型: integer。デフォルト: 1

  • num_workers_io

    I/Oタスク(ロード/リフレッシュ/ディスクへの/からの読込み)タスクに使用するワーカー・スレッドの数。ファイルベースのローダーは常に単一スレッドであるため、この値はこれらには影響しません。データベース・ローダーは、I/Oワーカーごとに新しい接続を開きます。デフォルト: <CPUの数>

例6-1 最小限のインメモリー・アナリスト構成

次の例を使用すると、インメモリー・アナリストにより、32のワーカーが含まれる分析スレッド・プールが初期化されます。(他のすべてのパラメータにデフォルト値が使用されます。)

{
  "enterprise_scheduler_config": {
    "analysis_task_config": {
      "max_threads": 32
    }
  }
}

例6-2 2つの事前ロードされたグラフ

複数のフィールドを設定し、PGXの起動時にメモリーにロードするための2つの固定グラフを指定します。

{ 
  "enterprise_scheduler_config": {
    "analysis_task_config": {
      "max_threads": 32
    },
    "fast_analysis_task_config": {
      "max_threads": 32
    }
  }, 
  "memory_cleanup_interval": 600,
  "max_active_sessions": 1, 
  "release_memory_threshold": 0.2, 
  "preload_graphs": [
    {
      "path": "graph-configs/my-graph.bin.json",
      "name": "my-graph"
    },
    {
      "path": "graph-configs/my-other-graph.adj.json",
      "name": "my-other-graph",
      "publish": false
    }
  ]
}

6.2.1 インメモリー・アナリストの構成ファイルの指定

インメモリー・アナリストの構成ファイルは、ServerInstance#startEngine (または任意のバリアント)が呼び出されるたびに起動時にインメモリー・アナリストによって解析されます。構成ファイルへのパスをインメモリー・アナリストに書き込むことも、プログラム的に指定することもできます。このトピックでは、ファイルを指定する複数の方法を識別します

プログラム的

すべての構成フィールドがJava列挙型として存在します。例:

Map<PgxConfig.Field, Object> pgxCfg = new HashMap<>();
pgxCfg.put(PgxConfig.Field.MEMORY_CLEANUP_INTERVAL, 600);

ServerInstance instance = ...
instance.startEngine(pgxCfg);

明示的に設定されていないすべてのパラメータにデフォルト値が使用されます。

ファイルの明示的な使用

地図の代わりに、インメモリー・アナリスト構成JSONファイルへのパスを書き込むことができます。例:

instance.startEngine("path/to/pgx.conf"); // file on local file system
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/opg --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の実行

opg> g = session.readGraphWithProperties("/opt/oracle/oracle-spatial-graph/property_graph/examples/pgx/graphs/sample.adj.json", "my-graph")
==> ...
opg> 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);

6.4.2 エッジリスト形式でのグラフのディスクへの格納

この例では、グラフ、Pagerank分析の結果、および元のエッジ・プロパティすべてをエッジリスト形式でディスクに格納します。

グラフを格納するには、次を指定する必要があります。

  • グラフの形式

  • ファイルが格納されるパス

  • 格納されるプロパティ。VertexProperty.ALLまたはEdgeProperty.ALLを指定するとすべてのプロパティが格納され、VertexProperty.NONEまたはEdgePropery.NONEを指定すると、どのプロパティも格納されません。個々のプロパティを指定するには、格納するVertexPropertyまたはEdgePropertyオブジェクトを渡します。

  • 既存のファイルを同じ名前で上書きするかどうかを示すフラグ

次の例では、/tmp/sample_pagerank.elist.json構成ファイルでグラフ・データを/tmp/sample_pagerank.elistに格納します。戻り値は、格納されているファイルのグラフ構成です。これは再度、グラフの読取りに使用できます。

シェルを使用したグラフの格納

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

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の実行

opg> analyst.countTriangles(graph, true)
==> 1

このアルゴリズムでは、サンプル・グラフ内の1つの三角形を検出します。

ヒント:

インメモリー・アナリスト・シェルを使用する場合、ロギング・レベルを変更すると、実行中のログ出力の量を増加できます。:h :loglevelを指定した:loglevelコマンドの実行に関する情報を参照してください。

Javaを使用したTriangle Countingの実行

import oracle.pgx.api.*;
 
Analyst analyst = session.createAnalyst();
long triangles = analyst.countTriangles(graph, true);

6.5.3 Pagerankアルゴリズムの実行

Pagerankは、グラフ内のそれぞれの頂点(ノード)について、01の間のランク値を計算し、その値をdoubleプロパティに格納します。このため、アルゴリズムによって、出力に対してタイプdouble頂点プロパティが作成されます。

インメモリー・アナリストでは、頂点プロパティとエッジ・プロパティの2つのタイプがあります。

  • 永続プロパティ: データ・ソースからグラフとともにロードされ固定されたディスク上のデータのインメモリー・コピーであるため、永続となるプロパティ。永続プロパティは読取り専用のため変更できず、セッション間で共有されます。

  • 一時プロパティ: 一時プロパティには値が書き込めるため、セッションでプライベートに使用されます。一時プロパティは、PgxGraphオブジェクトでcreateVertexPropertyおよびcreateEdgePropertyを呼び出して作成できます。

この例では、Pagerank値が最も高い上位3つの頂点を取得します。タイプdoubleの一時頂点プロパティを使用して、計算したPagerank値を保持します。Pagerankアルゴリズムでは、入力パラメータのデフォルト値としてエラー許容差 = 0.001、ダンピング係数 = 0.85、および反復の最大数 = 100のデフォルト値を使用します。

シェルを使用したPageRankの実行

opg> rank = analyst.pagerank(graph, 0.001, 0.85, 100);
==> ...
opg> 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());
}

6.6 カスタムPGXグラフ・アルゴリズムの使用

カスタムPGXグラフ・アルゴリズムを使用すると、Javaでグラフ・アルゴリズムを記述し、効率的なパラレル実装に自動的にコンパイルできます。

次のサブトピックに記載されている情報よりも詳しい情報は、https://docs.oracle.com/cd/E56133_01/latest/PGX_Algorithm_Language_Specification.pdfのPGXアルゴリズムの仕様を参照してください。

6.6.1 カスタムPGXアルゴリズムの作成

PGXアルゴリズムは、@graphAlgorithmの注釈が付けられている単一のクラス定義が含まれた通常の.javaファイルです。次に例を示します。

import oracle.pgx.algorithm.annotations.GraphAlgorithm;

@GraphAlgorithm
public class MyAlgorithm {
    ...
}

PGXアルゴリズム・クラスには、エントリ・ポイントとして使用されるパブリック・メソッドが1つだけ含まれている必要があります。次に例を示します。

import oracle.pgx.algorithm.PgxGraph;
import oracle.pgx.algorithm.VertexProperty;
import oracle.pgx.algorithm.annotations.GraphAlgorithm;
import oracle.pgx.algorithm.annotations.Out;

@GraphAlgorithm
public class MyAlgorithm {
    public int myAlgorithm(PgxGraph g, @Out VertexProperty<Integer> distance) {
        System.out.println("My first PGX Algorithm program!");

        return 42;
    }
}

通常のJavaメソッドと同様に、PGXアルゴリズムのメソッドは値(この例では整数)を戻すことができます。さらに興味深いのは、頂点プロパティdistanceを出力パラメータとしてマークする@Out注釈です。呼出し元は、出力パラメータを参照渡しします。このようにして、呼出し側はアルゴリズムの終了後に、変更されたプロパティへの参照を持ちます。

6.6.1.1 コレクション

コレクションを作成するには、.create()関数を呼び出します。たとえば、VertexProperty<Integer>は次のように作成されます。

VertexProperty<Integer> distance = VertexProperty.create();

特定の頂点vでプロパティの値を取得するには、次のようにします。

distance.get(v);

同様に、特定の頂点vのプロパティを値eに設定するには、次のようにします。

distance.set(v, e);

コレクションのプロパティを作成することもできます。

VertexProperty<VertexSequence> path = VertexProperty.create();

ただし、PGXアルゴリズムの割当ては常に(参照ではなく)で行われます。これを明示的にするには、コレクションの割当て時に.clone()を呼び出す必要があります

VertexSequence sequence = path.get(v).clone();

値が値で渡される別の結果として、Javaメソッド.equals()ではなく==演算子を使用して等価性をチェックできるようになりました。次に例を示します。

PgxVertex v1 = G.getRandomVertex();
PgxVertex v2 = G.getRandomVertex();
System.out.println(v1 == v2);
6.6.1.2 反復

PGXアルゴリズムで発生する最も一般的な操作は、反復(すべての頂点のループ、頂点の近傍のループなど)およびグラフのトラバース(幅優先または深さ優先)です。すべてのコレクションは、forEachメソッドとforSequentialメソッドを公開します。これらのメソッドにより、コレクションをそれぞれ並列および順番に反復処理できます。

次に例を示します。

  • グラフの頂点を並列で反復処理するには、次のようにします。
    G.getVertices().forEach(v -> {
        ...
    });
    
  • グラフの頂点を順番に反復処理するには、次のようにします。
    G.getVertices().forSequential(v -> {
        ...
    });
    
  • グラフの頂点をrから幅優先でトラバースするには、次のようにします。
    import oracle.pgx.algorithm.Traversal;
    
    Traversal.inBFS(G, r).forward(n -> {
        ...
    });
    

    forward (またはbackward)ラムダ内部では、calling currentLevel()によって現在のBFS(またはDFS)トラバースのレベルにアクセスできます。

6.6.1.3 削減

これらのパラレル・ブロック内では、ラムダの外部に定義される変数をアトミックに更新または削減するのが一般的です。このアトミック削減は、Scalar<T>: reduceAdd, reduceMul, reduceAndなどでメソッドとして使用できます。たとえば、グラフ内の頂点の数をカウントするには、次のようにします。

public int countVertices() {
    Scalar<Integer> count = Scalar.create(0);

    G.getVertices().forEach(n -> {
        count.reduceAdd(1);
    });

    return count.get();
}

複数の値をアトミックに更新する場合があります。たとえば、最小のプロパティ値と、その最小値にプロパティ値が到達した頂点を検出する場合があります。パラレル実行のために、2つの別々の削減文によって一貫性がない状態になる場合があります。

この問題を解決するために、ReductionsクラスにはargMin関数とargMax関数が用意されています。argMinの最初の引数は現在の値で、2番目の引数は潜在的な新しい最小値です。また、ArgMinMaxオブジェクトのandUpdate呼び出しを連鎖させて、その他の変数と、それらが(アトミックに)更新された後の値を指定できます。次に例を示します。

VertexProperty<Integer> rank = VertexProperty.create();
int minRank = Integer.MAX_VALUE;
PgxVertex minVertex = PgxVertex.NONE;

G.getVertices().forEach(n ->
    argMin(minRank, rank.get(n)).andUpdate(minVertex, n)
);

6.6.2 PGXアルゴリズムのコンパイルおよび実行

カスタムPGXアルゴリズムをコンパイルおよび実行できるようにするには、次のいくつかの処理を実行する必要があります。

  1. conf/pgx.confファイルの2つの構成パラメータを設定します。
    • graph_algorithm_languageオプションをJAVAに設定します。
    • java_home_dirオプションを、Javaホームへのパスに設定します(PGXにシステム・プロパティからJavaホームを推測させるには、<system-java-home-dir>を使用します)。
  2. セッションを作成します(シェルで暗黙的に、またはJavaで明示的に行います)。次に例を示します。
    cd $PGX_HOME
    ./bin/opg
    
  3. PGXアルゴリズムをコンパイルします。次に例を示します。
    myAlgorithm = session.compileProgram("/path/to/MyAlgorithm.java")
  4. アルゴリズムを実行します。次に例を示します。
    graph = session.readGraphWithProperties("/path/to/config.edge.json")
    property = graph.createVertexProperty(PropertyType.INTEGER)
    myAlgorithm.run(graph, property)
    

6.6.3 カスタムPGXアルゴリズムの例: Pagerank

次に、PGXアルゴリズムとしてpagerankを実装します。

import oracle.pgx.algorithm.PgxGraph;
import oracle.pgx.algorithm.Scalar;
import oracle.pgx.algorithm.VertexProperty;
import oracle.pgx.algorithm.annotations.GraphAlgorithm;
import oracle.pgx.algorithm.annotations.Out;

@GraphAlgorithm
public class Pagerank {
  public void pagerank(PgxGraph G, double tol, double damp, int max_iter, boolean norm, @Out VertexProperty<Double> rank) {
    Scalar<Double> diff = Scalar.create();
    int cnt = 0;
    double N = G.getNumVertices();

    rank.setAll(1 / N);
    do {
      diff.set(0.0);
      Scalar<Double> dangling_factor = Scalar.create(0d);

      if (norm) {
        dangling_factor.set(damp / N * G.getVertices().filter(v -> v.getOutDegree() == 0).sum(rank::get));
      }

      G.getVertices().forEach(t -> {
        double in_sum = t.getInNeighbors().sum(w -> rank.get(w) / w.getOutDegree());
        double val = (1 - damp) / N + damp * in_sum + dangling_factor.get();
        diff.reduceAdd(Math.abs(val - rank.get(t)));
        rank.setDeferred(t, val);
      });
      cnt++;
    } while (diff.get() > tol && cnt < max_iter);
  }
}

6.7 サブグラフの作成

メモリーにロードされたグラフに基づいてサブグラフを作成できます。

フィルタ式を使用するか、2部グラフの左側の集合を指定する頂点(ノード)に基づく2部サブグラフを作成できます。

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

6.7.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.7.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"));

6.7.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"));

6.7.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.7.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);

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

6.7.6 式フィルタを使用した一連の頂点またはエッジの作成

式フィルタを使用したサブグラフの作成(他のトピックで説明しています)以外にも、式フィルタを使用してグラフから一連の頂点またはエッジのみを選択することもできます。

たとえば、次の頂点フィルタ式を使用して「フィルタ式について」のサンプル・グラフで頂点セットを作成できます。

vertex.prop1 < 10

これにより、ID値99および333を持つ頂点セットが生成されます。

例6-3 頂点セットの作成

シェルの例:

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-4 エッジ・セットの作成

シェルの例:

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.7.7 頂点集合を使用した2部サブグラフの作成

2部サブグラフは、左側に使用される頂点(ノード)集合を指定して作成できます。2部サブグラフには、左側の頂点集合と右側の頂点集合の間にのみエッジがあります。左側の2つの頂点(ノード)間など、これらの集合内にエッジはありません。インメモリー・アナリストでは、入力および出力エッジが削除されたために分離された頂点は、2部サブグラフの一部ではありません。

次の図は、2部サブグラフを示します。プロパティは示していません。

次の例では、図6-1で作成した単一のグラフから2部サブグラフを作成します。左側の頂点集合を作成し、それに頂点を入力します。

シェルを使用した2部サブグラフ作成

opg> s = graph.createVertexSet()
==> ...
opg> s.addAll([graph.getVertex(333), graph.getVertex(99)])
==> ...
opg> s.size()
==> 2
opg> 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.8 グラフを使用したパターンマッチング問合せの使用

インメモリー・グラフに対してパターンマッチング問合せを発行してから、その問合せの結果を操作できます。

パターンマッチング問合せの例のデータ・セット

パターンマッチングの例では、2つの異なるデータ・セットを使用します。

  • 政治家、スポーツ選手、著名人および会社の間の関係

  • 装置、結線およびスイッチが含まれる電気ネットワーク

PGQLを使用したパターンマッチング問合せの発行

Property Graph Suery Language (PGQL)でグラフのパターンマッチング問合せを発行できます。PGQLは、SQLに似た宣言言語で、頂点とエッジ、および頂点とエッジのプロパティに関する制約で構成されたパターンを表現できます。

インメモリー・アナリストに対する問合せを発行するには、PgxGraph (sessionを使用してグラフをロードするときに取得するオブジェクトのタイプ)のqueryPgql() Javaメソッドを使用します。

次のトピックでは、問合せのパターンマッチングを使用します。

6.8.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に対する問合せの発行:

シェルの例:

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

PgqlResultSetは、問合せの結果セットを管理します。結果セットには、複数の結果が含まれます(このような問合せでは、多くのサブグラフが照合される場合があります)。各結果は、結果要素のリストで構成されています。結果要素の順序は、問合せのSELECT句内の変数の順序に従います。

問合せ結果を反復することは、一連のPgqlResultElementインスタンスを反復することを意味します。PgqlResultElementは、結果要素の型および変数名を保持します。

PgqlResultElementインスタンスのリストは、次のように取得できます。

シェルの例:

opg> resultElements = resultSet.getPgqlResultElements()

Javaの例:

import oracle.pgx.api.*;
import java.util.List;

...

List<PgqlResultElement> resultElements = resultSet.getPgqlResultElements();

最初の結果要素の型および変数名を取得します。

シェルの例:

opg> resultElement = resultElements.get(0)
opg> type = resultElement.getElementType() // STRING
opg> 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

ループのfor-eachスタイルを使用して結果セットを反復します。ループ内では、問合せ結果が含まれるPgqlResultインスタンスを取得します。

シェルの例:

opg> resultSet.getResults().each { \
       // the variable 'it' is implicitly declared to references each PgqlResult instance
     }

Javaの例:

import oracle.pgx.api.*;

...

for (PgqlResult result : resultSet.getResults()) {
  ...
}

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

opg> 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インスタンスまたはそれらの要素のハンドルを取得することもできます。

結果要素の索引別:

opg> nameX = it.getString(0)
opg> nameZ = it.getString(1)

結果要素の変数名別:

opg> nameX = it.getString("x.name")
opg> nameZ = it.getString("z.name")

型を知らずに結果要素を取得することもできます。

opg> nameX = it.get(0)
// or
opg> nameX = it.get("x.name")

6.8.2 例: 協力者の最も多い上位10人

この例では、グラフ内の協力者の最も多い上位10人を協力者の数の降順で見つけます。このような問合せではPGQLの様々な機能を活用しますが、これには、WHERE句で見つかったグラフ・パターンのグループ化、集計、順序付けおよび制限が含まれます。次の問合せ文字列は、PGQLでのユーザーの照会を表します。

opg> 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人の名前および協力者数を表示します。

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

この例では、頂点間で到達可能性をテストします。

ここでは、次の図の電気ネットワークのグラフを使用します。(データファイルは/opt/oracle/oracle-spatial-graph/property_graph/data/electric-network/electric_graph.edge.jsonにあります。)

図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.9 インメモリー・アナリスト・サーバーの起動

Big Data Spatial and Graphには、スクリプトの実行によってインメモリー・アナリスト・サーバーを起動できるApache Tomcatの事前構成済バージョンがバンドルされています。

サーバーを起動する前に構成する必要がある場合は、「インメモリー・アナリスト・サーバーの構成」を参照してください。

サーバーを起動するには、スクリプト/opt/oracle/oracle-spatial-graph/property_graph/pgx/bin/start-serverを実行します

6.9.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.10 Apache Tomcatへのデプロイ

インメモリー・アナリストはApache TomcatまたはOracle WebLogic Serverにデプロイできます。この例では、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/opg --base_url http://localhost:8080/pgx
    

関連項目:

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

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

6.11 Oracle WebLogic Serverへのデプロイ

インメモリー・アナリストはApache TomcatまたはOracle WebLogic Serverにデプロイできます。

この例では、Webアプリケーションとしてインメモリー・アナリストをOracle WebLogic Serverにデプロイする方法を示しています。(Big Data Spatial and Graph 2.5.3はOracle WebLogic Server 12.2.1.3では機能しません)

注意:

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

6.11.1 Oracle WebLogic Serverのデプロイ

注意:

Big Data Spatial and Graph 2.5.3はOracle WebLogic Server 12.2.1.3では機能しません。

Oracle WebLogic Serverのダウンロードおよびインストールについては、次を参照してください。

https://www.oracle.com/technetwork/middleware/weblogic/downloads/wls-for-dev-1703574.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クラスタ(またはApache TomcatあるいはOracle WebLogic上のWebアプリケーションとしてHadoopのないクライアント・システム)にインストールされた後、インメモリー・アナリスト・サーバーに接続できます。

6.12.1 インメモリー・アナリスト・シェルによる接続

インメモリー・アナリスト・インスタンスへの最も単純な接続方法は、サーバーのベースURLを指定することです。

--base_urlコマンド・ライン引数を使用して、そのベースURL上で実行されているサーバーに接続できます。たとえば、サーバーのSSL/TLSが無効であり、認証が必要なく、サーバーがhttp://localhost:8080/pgx上で実行されている場合、次を入力することにより、PGXシェルを使用してサーバーに接続できます。

cd $PGX_HOME
./bin/opg --base_url http://scott:<password>@localhost:8080/pgx

同じ方法でリモート・インスタンスに接続できます。

サーバーにBASIC認証が必要である場合、次の例のようにユーザー名およびパスワードを指定できます。

./bin/opg --base_url http://localhost:8080/pgx --username scott --password <password-for-scott>

サーバーのSSL/TLSが有効である場合、--truststoreオプションを使用して、サーバー証明書を検証するために使用される信頼ストアへのパスを(JKS形式で)指定できます。

./bin/opg --base_url https://localhost:8080/pgx --truststore path/to/truststore.jks

サーバーの双方向SSL/TLSが有効である場合、--keystoreおよび–-passwordオプションを使用して、クライアント証明書およびキーストア・パスワードが含まれるキーストア・ファイルを指定できます。

./bin/opg --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に設定します。

opg> :loglevel oracle.pgx DEBUG
===> log level of oracle.pgx logger set to DEBUG
opg> 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.13 PGXパーティション化グラフの使用

プロパティ・グラフをパーティション化グラフとしてインメモリー分析サーバー(PGX)にロードすると、メモリーが大幅に節約されます。

インメモリー・パーティション化グラフ・モデルは、グラフが異なるの頂点およびエッジを持ち、それぞれの型の頂点またはエッジが異なるプロパティ・セットを持つ場合に特に適しています。

たとえば、人と場所を表すグラフでは、Person (個人)型の頂点にはName (名前)やBirthday (誕生日)などのプロパティがあり、Place (場所)型の頂点にはAddress (住所)などのプロパティがあります。同様に、PersonからPersonへのエッジにはMeeting date (面会日)などのプロパティがあり、PersonからPlaceへのエッジにはLives at floor (居住階)などのプロパティがある場合があります。

パーティション化グラフの使用には、次の考慮事項があります。

  • NULL値を含むキーに対してGROUP BY集計を実行するPGQL問合せはサポートされていません。
  • パーティション分析アルゴリズム(パーティション・オブジェクトを返すアナリスト・メソッド)、頂点フィルタまたはエッジ・フィルタを使用するアルゴリズムおよびDijkstraアルゴリズムはサポートされません。
  • 一部の制約に従い、パーティション化グラフは変更セットを使用して変更できません。
  • パーティション化グラフは、GraphBuilder APIを使用して作成できません。

6.13.1 既存のプロパティ・グラフ・スキーマ(NoSQLまたはApache HBase)からのグラフの読取り

既存のOracleプロパティ・グラフ・スキーマのグラフをパーティション形式で読み取るには、グラフのconfigファイルのpartition_while_loadingフラグをtrueに設定します。

次に、NoSQLの例を示します。

{
  "format": "pg",
  "db_engine": "nosql",
  "partition_while_loading": "by_label",
  "hosts": [
    "my-host1:5000",
    "my-host2:5000",
    "my-host3:5000"
  ],
  "store_name": "my-store",
  "name": "my-graph",
  "vertex_props": [{
    "name": "prop",
    "type": "float"
  }],
  "edge_props": [{
    "name": "name",
    "type": "string"
  }, {
    "name": "cost",
    "type": "double"
  }]
}

メモリー内のパーティション化モデルにグラフをロードしない場合は、partition_by_labelフラグの値をnoに設定します。

Apache HBaseから読み取られるグラフのconfigファイルまたはフラット・ファイル(opv/ope)にも同じpartition_by_labelフラグを設定できます。

6.13.2 CSVファイルからのグラフの読取り

次の例では、2つのCSVファイルからグラフを読み取り、メモリー内のパーティション化モデルにロードします。

{
  "name": "simpleGraph",
  "vertex_providers":[{
    "name": "simpleVertexProvider",
    "format": "csv",
    "uris": ["simple.csv"],
    "key_column": 0
  }],
  "edge_providers":[{
    "name": "simpleEdgeProvider",
    "format": "csv",
    "uris": ["simple.csv"],
    "source_vertex_provider":"simpleVertexProvider",
    "destination_vertex_provider":"simpleVertexProvider",
    "key_column": 0,
    "source_column": 1,
    "destination_column": 2
  }]
}

メモリー内のパーティション化グラフにロードする構成ファイルは、次の例に示すように、プログラムによって作成することもできます。

HeterogeneousGraphConfigBuilder configBuilder = GraphConfigBuilder.forHeterogeneous().setName("simpleGraph");
 
FileEntityProviderConfigBuilder vertexProviderBuilder1 = new FileEntityProviderConfigBuilder(ProviderFormat.CSV)
    .setName("simpleVertexProvider1")
    .setKeyColumn(1)
    .addUri("simple1.csv");
 
FileEntityProviderConfigBuilder vertexProviderBuilder2 = new FileEntityProviderConfigBuilder(ProviderFormat.CSV)
    .setName("simpleVertexProvider2")
    .setKeyColumn(1)
    .addUri("simple2.csv");
 
FileEntityProviderConfigBuilder edgeProviderBuilder = new FileEntityProviderConfigBuilder(ProviderFormat.CSV)
    .setName("simpleEdgeProvider")
    .addUri("simple.csv")
    .setSourceVertexProvider("simpleVertexProvider1")
    .setDestinationVertexProvider("simpleVertexProvider2")
    .setKeyColumn(1)
    .setSourceColumn(2)
    .setDestinationColumn(3);
 
HeterogeneousGraphConfig graphConfig = configBuilder
    .addVertexProvider(vertexProviderBuilder1)
    .addVertexProvider(vertexProviderBuilder2)
    .addEdgeProvider(edgeProviderBuilder)
    .build();

グラフのconfigファイルが生成されたら、通常のreadGraphWithProperties() APIを使用して、グラフをPGXに読み込むことができます。

6.13.3 パーティション化グラフの頂点IDおよびエッジID

PGXはデフォルトで、グラフの頂点とエッジごとに一意の識別子の存在を強制しています。

これは、PgxGraph.getVertex(ID id)およびPgxGraph.getEdge(ID id)メソッド、または組込みのid()メソッドを使用するPGQL問合せでこれらを取得できるようにするためです。このことは、パーティション化グラフの場合もそのままです。

IDを生成するデフォルトの方法は、グラフのロード中に指定されたキーを使用することです。その場合、各頂点はすべての型の頂点に対して一意である頂点キーを持つ必要があります。同様に、エッジはデフォルトでグラフ全体に対して一意のエッジ・キーを持つ必要があります。

ただし、パーティション化グラフでこのような識別子を定義するのは面倒であるため、vertex_id_strategyおよびedge_id_strategyグラフ構成フィールドを値no_idsに設定することによって、頂点またはエッジ(あるいはその両方)の要件を無効にできます。頂点(resp. edge) IDを無効にすることは、前に示した頂点を含む、頂点(resp. edge) IDを使用したAPIへの呼び出しをPGXが禁止することを意味します。

6.13.4 PGQLでのパーティション化グラフの問合せ

パーティション化グラフでは、一部の頂点またはエッジにすべてのプロパティが定義されていない場合があります。

このプロパティを持たない頂点またはエッジに対してプロパティ・アクセスが試行されると、PGQL問合せエンジンはこのアクセスの結果としてNULL値を提供し、問合せを続行します。このNULL値が式の残りの問合せで使用される場合、SQL 3値論理と同じルールが式の評価に使用されます。

ORDER BY句でのNULL値のソートがサポートされており、NULL値は、昇順の並べ替えを使用する場合はNULL以外の値の後に配置され、降順の並べ替えを使用する場合はNULL以外の値の前に配置されます。

6.14 PGXロード・バランシングおよび高可用性のためのHAProxyの使用

HAProxy (高可用性プロキシ)は、Webサーバーで着信リクエストを複数のエンドポイントに分散できる、TCP/HTTPロード・バランサおよびプロキシ・サーバーです。

高可用性を実現するために、HAProxyをインメモリー分析サーバー(PGX)と一緒に使用できます。このトピックの例では、PGXに接続するクライアントとしてopgシェルを使用します。

このトピックの手順を使用するには、「インメモリー・アナリスト・サーバーの起動」の説明に従って、インメモリー・アナリスト・サーバーがすでにインストールおよび構成されている必要があります。

  1. HAProxyがまだBig Data ApplianceまたはOracle Linuxディストリビューションにインストールされていない場合は、次のコマンドを実行します。
    yum install haproxy
  2. PGXサーバーを起動します。

    たとえば、Big Data Applianceの4つのノード(bda02、bda03、bda04、bda05など)にわたってPGXをロード・バランシングする場合は、これらの各ノードでPGXを開始し、ポート7007をリッスンします。

  3. HAProxyを構成します。

    次の内容を含む新しいファイルhaproxy.cfgを作成します。(この例では、HAProxyはホストbda01上のポート8888をリッスンします)

    global
        maxconn 50000
        log /dev/log local0
     
    defaults
        mode http
        option httplog
        log global
        option forwardfor
        timeout connect 5s
        timeout client 5s
        timeout server 5s
        balance source
        hash-type consistent
     
    listen www
        bind :8888
        server web1 bda02:7007 check
        server web2 bda03:7007 check
        server web3 bda04:7007 check
        server web4 bda05:7007 check
    

    balance sourceを指定すると、クライアントのIPアドレスが対応するサーバーのIPアドレスにマップされます。PGXサーバーは分析セッション中にセッションのスティッキネスに依存するため、これは重要です。(HAProxyの構成の詳細は、http://cbonte.github.io/haproxy-dconv/2.0/intro.htmlの公式ドキュメントを参照してください。)

  4. ロード・バランサを起動します。

    前の手順で作成した構成ファイルを渡すことによって、bda01のHAProxyを起動します。

    haproxy -- haproxy.cfg
  5. ロード・バランサをテストします。

    任意のクライアント・ホストから、エンドポイントをbase_urlパラメータとしてopgクライアント・シェルに渡して、HAProxyサーバーに接続します。次に例を示します。

    cd /opt/oracle/oracle-spatial-graph/property_graph
    ./bin/opg --base_url http://bda01:8888
    

    サーバーが停止すると、インメモリー状態は失われます。HAProxyはコマンドを別のサーバーにルーティングしますが、クライアントはグラフをロードしたスクリプトを再実行するなどを行う必要があります。

    一連のPGXコマンドを実行してセッション・アフィニティをテストすることをお薦めします。サーバーを強制終了し、opgシェルを再起動して、HAProxyがリクエストを新しいサーバーにリダイレクトしていることを確認します。

6.15 HDFSでのデータの読取りおよび格納

インメモリー・アナリストでは、Hadoop Distributed File System (HDFS)をサポートしています。この例では、インメモリー・アナリストAPIを使用してHDFSのグラフ・データを読み取り、アクセスする方法を示しています。

グラフ構成ファイルはクライアント側で解析されます。グラフ・データと構成ファイルはHDFSに格納されます。Hadoopクライアントはインメモリー分析と同じコンピュータにインストールする必要があります。『Oracle Big Data Applianceソフトウェア・ユーザーズ・ガイド』を参照してください。

注意:

インメモリー・アナリスト・エンジンは、Hadoopクラスタの1つのノードのメモリーでのみ実行されます。

6.15.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.15.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.15.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.16 PGX RESTエンドポイントの使用の開始

PGX REST APIを使用すると、Java以外の言語でインメモリー・アナリストとやりとりして独自のクライアントを実装できます。

PGX RESTエンドポイントの使用に際し、このトピックでは次のことを前提としています。

  • curlを含むLinuxがインストールされていること。(curlは、RESTエンドポイントと対話するための単純なコマンドライン・ユーティリティです。)
  • PGXサーバーが起動し、http://localhost:7007で稼働していること。
  • PGXサーバーで認証/認可が無効になっていること。これはデフォルト以外の設定で、本番用には推奨されません (/opt/oracle/oracle-spatial-graph/property_graph/pgx/conf/server.conf内)。
    "enable_tls": false
  • PGXを使用すると、ローカル・ファイル・システムからのグラフの読取りが可能になります。これはデフォルト以外の設定で本番用には推奨されません(/opt/oracle/oracle-spatial-graph/property_graph/pgx/conf/pgx.conf内)。:
    "allow_local_filesystem": true

サポートされるエンドポイントの完全なリストを表示するには、http://localhost:7007/swagger.jsonを開きます。

ステップ1: CSRFトークンの取得

CSRFトークンをリクエストします。

curl -v http://localhost:7007/token

レスポンスは次のようになります。

*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 7007 (#0)
> GET /token HTTP/1.1
> Host: localhost:7007
> User-Agent: curl/7.47.0
> Accept: */*
> 
< HTTP/1.1 201
< SET-COOKIE: _csrf_token=9bf51c8f-1c75-455e-9b57-ec3ca1c63cc0;Version=1; HttpOnly
< Content-Length: 0

レスポンス内に表示されるとおり、cookie _csrf_tokenはトークン値に設定されます。この例で、9bf51c8f-1c75-455e-9b57-ec3ca1c63cc0は後続のリクエストに対するトークンです。書込みリクエストの場合、PGXサーバーではcookieとペイロードの両方に同じトークンが存在している必要があります。

ステップ2:セッションの作成

新規セッションを作成するには、JSONペイロードを送信します。

curl -v --cookie '_csrf_token=9bf51c8f-1c75-455e-9b57-ec3ca1c63cc0' -H 'content-type: application/json' -X POST http://localhost:7007/core/v1/sessions -d '{"source":"my-application", "idleTimeout":0, "taskTimeout":0, "timeUnitName":"MILLISECONDS", "_csrf_token":"9bf51c8f-1c75-455e-9b57-ec3ca1c63cc0"}'

my-applicationを、実行中のアプリケーションを示す値に置き換えます。この値は、サーバー管理者がセッションをアプリケーションにマッピングするために使用できます。アイドル・タイムアウトおよびタスク・タイムアウトを0に設定した場合、セッションおよび送信されたタスクがタイムアウトするタイミングをサーバーが決定することを意味します。cookieヘッダーとJSONペイロードの両方に同じCSRFトークンを指定する必要があります。レスポンスは次のようになります。

*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 7007 (#0)
> POST /core/v1/sessions HTTP/1.1
> Host: localhost:7007
> User-Agent: curl/7.47.0
> Accept: */*
> Cookie: _csrf_token=9bf51c8f-1c75-455e-9b57-ec3ca1c63cc0
> content-type: application/json
> Content-Length: 159
> 
* upload completely sent off: 159 out of 159 bytes
< HTTP/1.1 201
< SET-COOKIE: SID=abae2811-6dd2-48b0-93a8-8436e078907d;Version=1; HttpOnly
< Content-Length: 0

レスポンスにより、作成されたセッションID値にcookieが設定されます。セッションID abae2811-6dd2-48b0-93a8-8436e078907dは、後続のリクエストの例として使用されます。

ステップ3:グラフの読込み

注意:

事前ロードしたグラフまたは別のセッションによってすでに公開されているグラフを分析する場合は、このステップをスキップできます。事前ロードしたグラフまたは公開したグラフにアクセスするために必要な情報は、グラフの名前のみです。

グラフを読み込むには、次の例に示すように、グラフ構成をJSONとしてサーバーに送信します。

curl -v -X POST --cookie '_csrf_token=9bf51c8f-1c75-455e-9b57-ec3ca1c63cc0;SID=abae2811-6dd2-48b0-93a8-8436e078907d'  http://localhost:7007/core/v1/loadGraph -H 'content-type: application/json'  -d  '{"graphConfig":<graph-config>,"graphName":null,"_csrf_token":"9bf51c8f-1c75-455e-9b57-ec3ca1c63cc0"}'

<graph-config>を、実際のPGXグラフ構成のJSON表現に置換します。Apache HBaseからプロパティ・グラフを読み込むグラフ構成の例を次に示します。

{
  "format": "pg",
  "db_engine": "hbase",
  "zk_quorum": "hbasenode01:2181",
  "name": "my_graph",
  "edge_label": true,
  "edge_props": [{
    "name": "cost",
    "type": "double"
  }],
  "error_handling": {
    "on_prop_conversion": "silent"
  }
}

"graphName": nullを渡すと、サーバーに名前を生成するよう通知します。

サーバーは、次のように応答します。

* upload completely sent off: 315 out of 315 bytes
< HTTP/1.1 202
< Location: http://localhost:7007/core/v1/futures/8a46ef65-01a9-4bd0-87d3-ffe9dfd2ce3c/status
< Content-Type: application/json;charset=utf-8
< Content-Length: 51
< Date: Mon, 05 Nov 2018 17:22:22 GMT
< 
* Connection #0 to host localhost left intact
{"futureId":"8a46ef65-01a9-4bd0-87d3-ffe9dfd2ce3c"}

非同期リクエストについて

PGX RESTエンドポイントの大部分は非同期です。結果が完成するまで接続をオープンしたままにしないで、PGXサーバーはタスクとして送信し、将来のIDをステータス・コード200でただちに返します。このIDは、クライアントがタスクのステータスを定期的にリクエストしたり、終了後に結果値をリクエストするために使用できます。前のレスポンスから、次のような将来のステータスをリクエストできます。

curl -v --cookie 'SID=abae2811-6dd2-48b0-93a8-8436e078907d'  http://localhost:7007/core/v1/futures/8a46ef65-01a9-4bd0-87d3-ffe9dfd2ce3c/status

これによって次のような値が返されます。

< HTTP/1.1 200
< Content-Type: application/json;charset=utf-8
< Content-Length: 730
< Date: Mon, 05 Nov 2018 17:35:19 GMT
< 
* Connection #0 to host localhost left intact
{"id":"eb17f75b-e4c1-4a66-81a0-4ff0f8b4cb92","links":[{"href":"http://localhost:7007/core/v1/futures/eb17f75b-e4c1-4a66-81a0-4ff0f8b4cb92/status","rel":"self","method":"GET","interaction":["async-polling"]},{"href":"http://localhost:7007/core/v1/futures/eb17f75b-e4c1-4a66-81a0-4ff0f8b4cb92","rel":"abort","method":"DELETE","interaction":["async-polling"]},{"href":"http://localhost:7007/core/v1/futures/eb17f75b-e4c1-4a66-81a0-4ff0f8b4cb92/status","rel":"canonical","method":"GET","interaction":["async-polling"]},{"href":"http://localhost:7007/core/v1/futures/eb17f75b-e4c1-4a66-81a0-4ff0f8b4cb92/value","rel":"related","method":"GET","interaction":["async-polling"]}],"progress":"succeeded","co

ステータスの他に(この場合は"succeeded")、この出力では、タスクを取り消す(DELETE)ためのリンク、および完了後にタスクの結果を取得するためのリンク(GET <future-id>/value)が提供されます。

curl -X GET --cookie 'SID=abae2811-6dd2-48b0-93a8-8436e078907d' http://localhost:7007/core/v1/futures/cdc15a38-3422-42a1-baf4-343c140cf95d/value

サーバーで生成された名前を含む、ロードされたグラフの詳細を返します(sample)。

{"id":"sample","links":[{"href":"http://localhost:7007/core/v1/graphs/sample","rel":"self","method":"GET","interaction":["async-polling"]},{"href":"http://localhost:7007/core/v1/graphs/sample","rel":"canonical","method":"GET","interaction":["async-polling"]}],"nodeProperties":{"prop1":{"id":"prop1","links":[{"href":"http://localhost:7007/core/v1/graphs/sample/properties/prop1","rel":"self","method":"GET","interaction":["async-polling"]},{"href":"http://localhost:7007/core/v1/graphs/sample/properties/prop1","rel":"canonical","method":"GET","interaction":["async-polling"]}],"dimension":0,"name":"prop1","entityType":"vertex","type":"integer","transient":false}},"vertexLabels":null,"edgeLabel":null,"metaData":{"id":null,"links":null,"numVertices":4,"numEdges":4,"memoryMb":0,"dataSourceVersion":"1536029578000","config":<graph-config>,"creationRequestTimestamp":1541242100335,"creationTimestamp":1541242100774,"vertexIdType":"integer","edgeIdType":"long","directed":true},"graphName":"sample","edgeProperties":{"cost":{"id":"cost","links":[{"href":"http://localhost:7007/core/v1/graphs/sample/properties/cost","rel":"self","method":"GET","interaction":["async-polling"]},{"href":"http://localhost:7007/core/v1/graphs/sample/properties/cost","rel":"canonical","method":"GET","interaction":["async-polling"]}],"dimension":0,"name":"cost","entityType":"edge","type":"double","transient":false}},"ageMs":0,"transient":false}

<graph-config>には、リクエストで送信したグラフ構成が含まれます。

簡略化のために、同期タスクのステータスまたは値の追加のリクエストはここではスキップされています。

ステップ4:プロパティの作成

ロードされたグラフでPageRankアルゴリズムを実行する場合もあります。そのためには、計算されたランク値を保持できるグラフ上で、DOUBLE型の頂点プロパティを作成する必要があります。

curl -v -X POST --cookie '_csrf_token=9bf51c8f-1c75-455e-9b57-ec3ca1c63cc0;SID=abae2811-6dd2-48b0-93a8-8436e078907d'  http://localhost:7007/core/v1/graphs/sample/properties -H 'content-type: application/json'  -d '{"entityType":"vertex","type":"double","name":"pagerank", "hardName":false,"dimension":0,"_csrf_token":"9bf51c8f-1c75-455e-9b57-ec3ca1c63cc0"}'

返される将来の結果をリクエストすると、次のような結果が返されます。

{"id":"pagerank","links":[{"href":"http://localhost:7007/core/v1/graphs/sample/properties/pagerank","rel":"self","method":"GET","interaction":["async-polling"]},{"href":"http://localhost:7007/core/v1/graphs/sample/properties/pagerank","rel":"canonical","method":"GET","interaction":["async-polling"]}],"dimension":0,"name":"pagerank","entityType":"vertex","type":"double","transient":true}

ステップ5:PageRankアルゴリズムの実行

次の例は、アルゴリズムを呼び出す方法を示しています。アルゴリズムIDはURLの一部であり、アルゴリズムに渡すパラメータはJSONペイロードの一部です。

curl -v -X POST --cookie '_csrf_token=9bf51c8f-1c75-455e-9b57-ec3ca1c63cc0;SID=abae2811-6dd2-48b0-93a8-8436e078907d' http://localhost:7007/core/v1/analyses/pgx_builtin_k1a_pagerank/run -H  'content-type: application/json' -d  '{"args":[{"type":"GRAPH","value":"sample"},{"type":"DOUBLE_IN","value":0.001},{"type":"DOUBLE_IN","value":0.85},{"type":"INT_IN","value":100},{"type":"BOOL_IN","value":true},{"type":"NODE_PROPERTY","value":"pagerank"}],"expectedReturnType":"void","workloadCharacteristics":["PARALLELISM.PARALLEL"],"_csrf_token":"9bf51c8f-1c75-455e-9b57-ec3ca1c63cc0"}'

将来の作業が完了すると、結果は次のようになります。

{"success":true,"canceled":false,"exception":null,"returnValue":null,"executionTimeMs":50}

ステップ6:PGQL問合せの実行

PageRankアルゴリズムの結果を問い合せるには、次の例に示すようにPGQL問合せを実行します。

curl -v -X POST --cookie '_csrf_token=9bf51c8f-1c75-455e-9b57-ec3ca1c63cc0;SID=abae2811-6dd2-48b0-93a8-8436e078907d' http://localhost:7007/core/v1/pgql/run -H 'content-type: application/json'  -d '{"pgqlQuery":"SELECT x.pagerank MATCH (x) WHERE x.pagerank > 0","semantic":"HOMOMORPHISM", "schemaStrictnessMode":true, "graphName" : "sample", "_csrf_token":"9bf51c8f-1c75-455e-9b57-ec3ca1c63cc0"}'

結果は、問合せの結果セットと対話するために使用できるリンクのセットです。

{"id":"pgql_1","links":[{"href":"http://localhost:7007/core/v1/pgqlProxies/pgql_1","rel":"self","method":"GET","interaction":["sync"]},{"href":"http://localhost:7007/core/v1/pgqlResultProxies/pgql_1/elements","rel":"related","method":"GET","interaction":["sync"]},{"href":"http://localhost:7007/core/v1/pgqlResultProxies/pgql_1/results","rel":"related","method":"GET","interaction":["sync"]},{"href":"http://localhost:7007/core/v1/pgqlProxies/pgql_1","rel":"canonical","method":"GET","interaction":["async-polling"]}],"exists":true,"graphName":"sample","resultSetId":"pgql_1","numResults":4}

結果セットの最初の2048要素をリクエストするには、次を送信します。

curl -X GET  --cookie 'SID=abae2811-6dd2-48b0-93a8-8436e078907d' http://localhost:7007/core/v1/pgqlProxies/pgql_1/results?size=2048

レスポンスは次のようになります。

{"id":"/pgx/core/v1/pgqlProxies/pgql_1/results","links":[{"href":"http://localhost:7007/core/v1/pgqlProxies/pgql_1/results","rel":"self","method":"GET","interaction":["sync"]},{"href":"http://localhost:7007/core/v1/pgqlProxies/pgql_1/results","rel":"canonical","method":"GET","interaction":["async-polling"]}],"count":4,"totalItems":4,"items":[[0.3081206521195582],[0.21367103988538017],[0.21367103988538017],[0.2645372681096815]],"hasMore":false,"offset":0,"limit":4,"showTotalResults":true}

6.17 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

これらの表からデータをグラフとしてロードするには、最初に構成ファイルを作成する必要があります。この構成ファイルには、表名、ユーザー名などが含まれています。

構成ファイルにパスワードを渡すには、Oracle JDKとともに自動的にインストールされるkeytoolコマンドライン・ユーティリティを使用して、新しいJavaキーストア・ファイルを作成します。次に例を示します。

keytool -importpass -alias database1 -keystore keystore.jks

次の入力を求めるプロンプトが表示されます。

  • キーストア・ファイルへのアクセスを保護するためのオプションのキーストア・パスワード。
  • 格納する実際のパスワード。これは後でdatabase1などの指定された別名と関連付けられます。複数のパスワードを同じキーストア・ファイルに格納できます。

別のパスワードを追加するには、異なる別名パラメータを使用して同じコマンドを再度使用します。次に例を示します。

keytool -importpass -alias database2 -keystore keystore.jks

keytoolコマンドの使用方法の詳細は、JDKのドキュメントhttps://docs.oracle.com/javase/8/docs/technotes/tools/unix/keytool.html#CHDBGFHEを参照してください。

シークレットを含むキーストア・ファイルがある場合、そのファイルをPGXに登録する必要があります。

  • クライアント・シェルを使用している場合は、--secret-storeコマンドライン・オプションを使用してファイルを登録できます。次に例を示します。

    ./bin/opg --secret_store path/to/keystore.jks
  • Javaアプリケーションを記述している場合は、グラフをメモリーに読み取る前に、PgxSession#registerKeystore(keystorePath, keystorePassword) APIを使用してキーストアを登録します。

キーストアが現在のセッションに登録されたら、グラフ構成ファイルをパスワードではなく別名を参照するように変更します。次に例を示します。

{
  "jdbc_url": "jdbc:oracle:thin:@localhost:1521:rdbmsod",
  "format": "two_tables",
  "datastore": "rdbms",
  "username": "scott",
  "keystore_alias": "database1",
  "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"
  }]
}

その後、通常のAPIを使用してグラフを読み取ります。たとえば、PgxGraph graph = session.readGraphWithProperties("config.json")などです。

NULL値の処理方法

インメモリー・アナリストの場合、ノードまたはエッジ内のプロパティ値をnullにすることはできません。このため、ノードまたはエッジ表内のプロパティ値がnullに設定されている場合は常に、代わりにデフォルト値が割り当てられます。configオブジェクトに指定されていない場合、デフォルト値はプロパティ・タイプのJavaデフォルト値です(たとえば、doubleに対する0.0など)。

ただし、次の例に示すように、configオブジェクトに異なるデフォルト値を指定することもできます。

{
  "name": "NP1",
  "type": "double",
  "default": 1.0
}

6.18 インメモリー・アナリストApache Zeppelinインタプリタの使用

インメモリー・アナリストには、Apache Zeppelinのインタプリタ実装が用意されています。このチュートリアルのトピックでは、ローカルのZeppelinインストールにインメモリー・アナリスト・インタプリタをインストールし、いくつかの簡単な操作を実行する方法について説明します。

インタプリタのインストール

次のステップはZeppelinバージョン0.8.1を使用してテストしたものであり、これよりバージョンが新しい場合は変更する必要がある場合があります。

  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()を呼び出します。

opg> execEnv = session.getExecutionEnvironment()
==> ExecutionEnvironment[session=576af1fd-73aa-4866-abf0-00a71757d75b]

実行環境は、3つのサブ環境(タスク・タイプごとに1つ)に分割されます。

  • IO環境: IOタスク用

  • 分析環境: CPUバウンドの分析タスク用

  • 高速分析環境: 軽量だがCPUバウンドの分析タスク用

実行環境の現在の状態を問い合せるには、getValues()メソッドを呼び出します。

opg> 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()メソッドが用意されています。

opg> ioEnv = execEnv.getIoEnvironment()
==> IoEnvironment[pool=io-pool]
opg> ioEnv.getValues()
==> num_threads_per_task=72

opg> analysisEnv = execEnv.getAnalysisEnvironment()
==> CpuEnvironment[pool=analysis-pool]
opg> analysisEnv.getValues()
==> max_num_threads=72
==> weight=72
==> priority=MEDIUM

opg> fastAnalysisEnv = execEnv.getFastAnalysisEnvironment()
==> CpuEnvironment[pool=fast-track-analysis-pool]
opg> fastAnalysisEnv.getValues()
==> max_num_threads=72
==> weight=1
==> priority=HIGH

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

IoEnvironmentsetNumThreadsPerTask()メソッドを使用することにより、I/O環境のスレッドの数を変更できます。この値は即時更新され、更新後に発行されたタスクはすべて、更新された値を使用して実行されます。

opg> ioEnv.setNumThreadsPerTask(8)
==> 8
opg> g = session.readGraphWithProperties(...)
==> PgxGraph[name=graph,N=3,E=6,created=0]

環境を初期値にリセットするには、reset()メソッドを呼び出します。

opg> ioEnv.reset()
==> null

CPU環境の場合、setWeight()、setPriority()およびsetMaxThreads()メソッドを使用してスレッドの重み、優先度および最大数を変更できます。

opg>  analysisEnv.setWeight(50)
==> 50
opg> fastAnalysisEnv.setMaxThreads(1)
==> 1
opg> rank = analyst.pagerank(g)
==> VertexProperty[name=pagerank,type=double,graph=graph]

ExecutionEnvironmentに対してreset()を呼び出すと、すべての環境を一度にリセットできます。

opg> 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のクロージャを使用する場合:

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