6.9.2.2 PGQL問合せでのパフォーマンスの考慮事項

次に、問合せのパフォーマンスのためのお薦めの慣例をいくつか示します。

再帰的問合せ

再帰的問合せの実行を高速化するために、次の索引をお薦めします。

  • 再帰パターンの基礎となるVERTEX表の場合、キー列の索引
  • 再帰パターンの基礎となるEDGE表の場合、ソース・キー列の索引

    ノート:

    (ソース・キー, 宛先キー)に索引を作成することもできます。

たとえば、次のCREATE PROPERTY GRAPH文について考えてみます。

CREATE PROPERTY GRAPH people
  VERTEX TABLES(
    person
      KEY ( id )
      LABEL person
      PROPERTIES( name, age )
  )
  EDGE TABLES(
    knows
      key (person1, person2)
      SOURCE KEY ( person1 ) REFERENCES person (id)
      DESTINATION KEY ( person2 ) REFERENCES person (id)
      NO PROPERTIES
  )
  OPTIONS ( PG_VIEW )

また、次の問合せも考えてみます。

SELECT COUNT(*)
FROM MATCH ANY SHORTEST ( (n:Person) -[e:knows]->* (m:Person) )
WHERE n.id = 1234

前述の問合せの再帰的部分のパフォーマンスを向上させるには、次の索引が存在する必要があります。

  • CREATE INDEX <INDEX_NAME> ON PERSON(ID)
  • CREATE INDEX <INDEX_NAME> ON KNOWS(PERSON1) または

    CREATE INDEX <INDEX_NAME> ON KNOWS(PERSON1, PERSON2)

コンポジット頂点キー

コンポジット頂点キーの場合、キー列にファンクション索引を作成することで、問合せの実行を最適化できます。

  • 再帰パターンの基礎となるVERTEX表の場合、カンマ区切りのキー列の連結に対するファンクション索引
  • 再帰パターンの基礎となるEDGE表の場合、カンマ区切りのソース・キー列の連結に対するファンクション索引

    ノート:

    (ソース・キー列, 宛先キー列)に索引を作成することもできます。

たとえば、次のCREATE PROPERTY GRAPH文について考えてみます。

CREATE PROPERTY GRAPH people
  VERTEX TABLES(
    person
      KEY ( id1, id2 )
      LABEL person
      PROPERTIES( name, age )
  )
  EDGE TABLES(
    knows
      key (id)
      SOURCE KEY ( id1person1, id2person1 ) REFERENCES person (id1,id2)
      DESTINATION KEY ( id1person2, id2person2 ) REFERENCES person (id1,id2)
      NO PROPERTIES
  )
  OPTIONS ( PG_VIEW )

また、次の問合せも考えてみます。

SELECT COUNT(*)
FROM MATCH ANY SHORTEST ( (n:Person) -[e:knows]->* (m:Person) )
WHERE n.id = 1234

前述の問合せの再帰的部分のパフォーマンスを向上させるには、次の索引が存在する必要があります。

  • CREATE INDEX <INDEX_NAME> ON PERSON (ID1 || ',' || ID2)
  • CREATE INDEX <INDEX_NAME> ON KNOWS (ID1PERSON1 || ',' || ID2PERSON1)または

    CREATE INDEX <INDEX_NAME> ON KNOWS (ID1PERSON1 || ',' || ID2PERSON1, ID1PERSON2 || ',' || ID2PERSON2)

コンポジット頂点キーの一部の列が文字列列である場合、その列は、ファンクション索引の作成でカンマをエスケープする必要があります。

たとえば、前述の例の表PERSONの列ID1の型がVARCHAR2(10)の場合、次のように列のカンマをエスケープする必要があります。

replace(ID1, ',', '\,')

そのため、パフォーマンスを向上させるための索引は次のようになります。

  • CREATE INDEX <INDEX_NAME> ON PERSON (replace(ID1, ',', '\,') || ',' || ID2)
  • CREATE INDEX <INDEX_NAME> ON KNOWS (replace(ID1PERSON1, ',', '\,') || ',' || ID2PERSON1)

問合せオプティマイザ・ヒントの使用

次のヒントを使用すると、PGQL可変長パス・パターンのSQLへの変換に影響を与えることができます。

  • REVERSE_PATH: 逆パス最適化のオンとオフを切り替えます(デフォルトではON)。ONの場合、指定されたフィルタ述語に基づいて、パターンを最適に評価できるは、ソースから宛先なのか宛先からソースなのかを自動的に判断します。
  • PUSH_SRC_HOPS: ソース・フィルタ最適化の強要のオンとオフを切り替えます(デフォルトではON)。ONの場合、フィルタ述語を使用して、ソース頂点(パス評価が逆の場合は宛先頂点)の数を制限し、それによって可変長パス・パターン評価の検索領域を制限します。
  • PUSH_DST_HOPS: 宛先フィルタ最適化の強要のオンとオフを切り替えます(デフォルトではOFF)。ONの場合、フィルタ述語を使用して、宛先頂点(パス評価が逆の場合はソース頂点)の数を制限し、それによって可変長パス・パターン評価の検索領域を制限します。

前述のヒントは、次のJava APIメソッドでoptionsパラメータとして構成できます。

  • executeQuery(String pgql, String options)
  • translateQuery(String pgql, String options)
  • execute(String pgql, String matchOptions, String options)

たとえば、次のPGQL問合せについて考えます。

SELECT v1.name AS v1, v2.name AS v2, v3.name As v3 
FROM MATCH (v1:Person)-[e1:friendOf]->(v2:Person), 
MATCH ANY (v2:Person)-[e2:friendOf]->*(v3:Person) 
WHERE v1.name= 'Bob'

PUSH_SRC_HOPSのデフォルト・オプションを使用して前述の問合せを実行すると、次のようにstart_nodes_translationの出力にフィルタ式が表示されます。

System.out.println(pgqlStatement.translateQuery(pgql).getSqlTranslation())
...
...
start_nodes_translation => (to_clob('SELECT ''PERSONS'' AS "src_table", e1.person_b AS "src_key"
FROM "GRAPHUSER"."PERSONS" "V1", "GRAPHUSER"."FRIENDSHIPS" "E1"
WHERE (((e1.person_a = v1.person_id) AND NOT(e1.person_b IS NULL)) AND (v1.name = ''Bob''))')),
     end_nodes_translation => (to_clob('SELECT ''PERSONS'' AS "dst_table", v3.person_id AS "dst_key"
FROM "GRAPHUSER"."PERSONS" "V3"')),
...
...

ヒントPUSH_SRC_HOPS=Fを指定して前述の問合せを実行すると、次のように問合せはSQLに変換されます。

System.out.println(pgqlStatement.translateQuery(pgql,"PUSH_SRC_HOPS=F").getSqlTranslation())

...
...start_nodes_translation => (to_clob('SELECT ''PERSONS'' AS "src_table", v2.person_id AS "src_key"
FROM "GRAPHUSER"."PERSONS" "V2"')),
     end_nodes_translation => (to_clob('SELECT ''PERSONS'' AS "dst_table", v3.person_id AS "dst_key"
FROM "GRAPHUSER"."PERSONS" "V3"')),
...
...

グラフ・メタデータ・キャッシュおよび変換キャッシュを使用した問合せ変換の高速化

次のグローバル・キャッシュは、PGQL問合せ変換の高速化に役立ちます。

  • グラフ・メタデータ・キャッシュ: 表、ラベル、プロパティなどのグラフ・メタデータを格納します。
  • 変換キャッシュ: PGQLからSQLへの変換を格納します。

次のJava APIを使用してキャッシュを構成できます。

  • clearTranslationCache()
  • disableTranslationCache()
  • enableTranslationCache()
  • setTranslationCacheMaxCapacity(int maxCapacity)
  • clearGraphMetadataCache()
  • disableGraphMetadataCache()
  • enableGraphMetadataCache()
  • setGraphMetadataCacheMaxCapacity(int maxCapacity)

前述のこれらのメソッドは、PgqlConnectionクラスに属します。個々のキャッシュはデータベース・ユーザーごとに保持されるため、キャッシュされたオブジェクトは、接続URLとその下のユーザーが同じである場合に、異なるPgqlConnectionオブジェクト間で共有されます。