DSE Graph、OLTP、およびOLAP

OLTPとOLAPは、DSE Graphがグラフ・データベースの検索に使用する異なる処理方法です。

オンライン・トランザクション処理(OLTP)は、短いオンライン・トランザクションが多数あり、クエリー処理が非常に速いという特徴があります。OLTPは通常、トランザクション指向のアプリケーションで、データ入力およびデータ取得に使用されます。オンライン分析処理(OLAP)は、一般的に、集積された履歴データを対象に複雑な計算を行う、データの多次元分析に使用されます。

OLTPアプリケーションでは、1秒未満の応答速度が求められます。一方、OLAPアプリケーションではクエリー終了まで長くかかります。グラフ・データベースは、ランダム・アクセス・データ・システムです。これらのデータベースのOLAP探索では、グラフ内のすべての頂点を線形にスキャンします。逆に、OLTP探索は、グローバル・グラフの特定のサブグラフに局限されます。OLTP探索では、インデックスを利用してグラフの特定の頂点に「ジャンプ」してから、サブグラフに対するスキャンを開始します。

OLTPクエリー

OLTPクエリーは、グラフ全体の限定されたサブセットにアクセスする必要がある問い合わせに最適です。OLTPクエリーでは、フィルターを使用して、回答を見つけるために巡回する頂点の数を制限します。DSE Graphでは、頂点が、そのエッジおよび隣接する頂点と一緒に配置されます。インデックスを使用した探索でサブグラフが指定されている場合、ディスクに対する要求の数は、要求されたサブグラフの位置を特定してメモリーに書き込むために削減されます。メモリーに書き込まれると、エッジに沿って頂点間を巡回します。

OLAPクエリー

OLAPクエリーは、グラフに保存されているデータのかなりの部分にアクセスしなければならない問い合わせに適しています。OLAPクエリーを評価するために前の方法を使用することは効率的ではないため、別のプロセスが使用されます。OLAPクエリーが処理される際、グラフ全体は、それぞれ、単一の頂点とそのプロパティ、インシデント・エッジ、エッジのプロパティから成る星型グラフのシーケンスとして解釈されます。この星型グラフは、すべての星型グラフが処理され、見つかったデータの集計が完了するまで1つの星型グラフから次の星型グラフへと直線的に処理されます。

グラフ探索の作成の原則

これらの基本的原則を理解することが、グラフ・データのクエリーを実行するためのより良いグラフ探索を記述することにつながります。簡単な例でこの違いを説明します。Julia Childが創作したレシピの数は?という、食べ物に関するグラフを使用したクエリーを取り上げることにします。

次のグラフ探索を見てみましょう。
g.V().in().has('name','Julia Child').count()
===>6

この探索で、次の処理が完了します。

  1. すべての頂点を見る。
  2. 内向きエッジを巡回する。
  3. Julia Childnameとプロパティ値のプロパティ・キーを持つ隣接する頂点を検索します。
  4. 頂点の数をカウントします。

このグラフ探索は典型的なOLAP探索です。この探索では、すべての頂点にタッチする必要があり、インデックスを使用しません。返されるカウントには、レシピだけでなくJulia Childに対するエッジを持つ頂点がすべて含まれます。後で説明しますが、カウント数は不正確で非常に大きくなります。

このクエリーを完了するために探索しなければならない要素の数を考えてみましょう。DSE Graphには、探索の分析に役立つプロファイリング機能があります。
gremlin> g.V().in().has('name','Julia Child').count().profile()
==>Traversal Metrics
Step                                                               Count  Traversers       Time (ms)    % Dur
=============================================================================================================
DsegGraphStep(vertex,[])                                              61          61          28.932    18.71
  query-optimizer                                                                              0.563
    \_condition=((label = FridgeSensor | label = author | label = book | label = ingredient | label = meal |
                label = recipe | label = reviewer) & (true))
  query-setup                                                                                  0.048
    \_isFitted=true
    \_isSorted=false
    \_isScan=true
  index-query                                                                                  0.979
    \_usesCache=false
    \_statement=SELECT "city_id", "sensor_id" FROM "DSEQuickStart"."FridgeSensor_p" WHERE "~~vertex_exists" =
                 ? LIMIT ? ALLOW FILTERING; with params (java.lang.Boolean) true, (java.lang.Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
  index-query                                                                                  0.862
    \_usesCache=false
    \_statement=SELECT "community_id", "member_id" FROM "DSEQuickStart"."author_p" WHERE "~~vertex_exists" =
                ? LIMIT ? ALLOW FILTERING; with params (java.lang.Boolean) true, (java.lang.Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
  index-query                                                                                  0.679
    \_usesCache=false
    \_statement=SELECT "community_id", "member_id" FROM "DSEQuickStart"."book_p" WHERE "~~vertex_exists" = ?
                LIMIT ? ALLOW FILTERING; with params (java.lang.Boolean) true, (java.lang.Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
  index-query                                                                                  1.344
    \_usesCache=false
    \_statement=SELECT "community_id", "member_id" FROM "DSEQuickStart"."ingredient_p" WHERE "~~vertex_exists
                " = ? LIMIT ? ALLOW FILTERING; with params (java.lang.Boolean) true, (java.lang.Integer) 5000
                0
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
  index-query                                                                                  1.053
    \_usesCache=false
    \_statement=SELECT "community_id", "member_id" FROM "DSEQuickStart"."meal_p" WHERE "~~vertex_exists" = ?
                LIMIT ? ALLOW FILTERING; with params (java.lang.Boolean) true, (java.lang.Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
  index-query                                                                                  4.173
    \_usesCache=false
    \_statement=SELECT "community_id", "member_id" FROM "DSEQuickStart"."recipe_p" WHERE "~~vertex_exists" =
                ? LIMIT ? ALLOW FILTERING; with params (java.lang.Boolean) true, (java.lang.Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
  index-query                                                                                  1.291
    \_usesCache=false
    \_statement=SELECT "community_id", "member_id" FROM "DSEQuickStart"."reviewer_p" WHERE "~~vertex_exists"
                = ? LIMIT ? ALLOW FILTERING; with params (java.lang.Boolean) true, (java.lang.Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
DsegVertexStep(IN,vertex)                                             78          78          95.721    61.90
  query-optimizer                                                                              0.305
    \_condition=((true) & direction = IN)
  vertex-query                                                                                 4.136
    \_usesCache=false
    \_statement=SELECT * FROM "DSEQuickStart"."author_e" WHERE "community_id" = ? AND "member_id" = ? LIMIT ?
                 ALLOW FILTERING; with params (java.lang.Integer) 588941056, (java.lang.Long) 0, (java.lang.I
                nteger) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
    \_isPartitioned=false
    \_usesIndex=false
  vertex-query                                                                                 0.558
    \_usesCache=false
    \_statement=SELECT * FROM "DSEQuickStart"."author_e" WHERE "community_id" = ? AND "member_id" = ? LIMIT ?
                 ALLOW FILTERING; with params (java.lang.Integer) 1432048000, (java.lang.Long) 1, (java.lang.
                Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
    \_isPartitioned=false
    \_usesIndex=false
  vertex-query                                                                                 1.146
    \_usesCache=false
    \_statement=SELECT * FROM "DSEQuickStart"."author_e" WHERE "community_id" = ? AND "member_id" = ? LIMIT ?
                 ALLOW FILTERING; with params (java.lang.Integer) 153541376, (java.lang.Long) 1, (java.lang.I
                nteger) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
    \_isPartitioned=false
    \_usesIndex=false
  query-setup                                                                                  0.941
    \_isFitted=false
    \_isSorted=true
    \_isScan=false
  query-setup                                                                                  0.015
    \_isFitted=false
    \_isSorted=true
    \_isScan=false
  vertex-query                                                                                 1.966
    \_usesCache=false
    \_statement=SELECT * FROM "DSEQuickStart"."author_e" WHERE "community_id" = ? AND "member_id" = ? LIMIT ?
                 ALLOW FILTERING; with params (java.lang.Integer) 138026496, (java.lang.Long) 0, (java.lang.I
                nteger) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
    \_isPartitioned=false
    \_usesIndex=false
  query-setup                                                                                  0.015
    \_isFitted=false
    \_isSorted=true
    \_isScan=false
  query-setup                                                                                  0.013
    \_isFitted=false
    \_isSorted=true
    \_isScan=false
  query-setup                                                                                  0.016
    \_isFitted=false
    \_isSorted=true
    \_isScan=false
NoOpBarrierStep(2500)                                                 78          25           2.877     1.86
HasStep([name.=(Julia Child)])                                         5           1          25.242    16.32
CountGlobalStep                                                        1           1           1.859     1.20
                                            >TOTAL                     -           -         154.632        -
注: 各ステップに要する時間は、キャッシングおよびその他の要因に左右されます。報告される時間はあくまで解説を目的としたものなので、無視してください。現在、profile()メソッドには、Gremlinコマンドの結果実行されるCQLコマンドが含まれています。
1. Studioによる探索1のプロファイル出力

最初のステップを見ると、グラフ内のすべての頂点が探索されています。このグラフは非常に小規模なため、頂点の数は、プロダクション・グラフと比べて無視できます。次のステップでは、頂点に入ってくるすべてのエッジを検出する必要があります。繰り返しになりますが、小規模なグラフの場合、エッジの数はごく少数ですが、プロダクション・グラフのエッジ数は数百万から数十億になります。ここでは、隣接頂点をフィルター処理して頂点の数を6にまで絞り込むことによって、指定されたプロパティ・キー情報を見つけます。最後の2つのステップでは、カウントおよびプロファイリング測定を完了します。

エッジ・ラベルの指定

それでは、内向きエッジのエッジ・ラベルを指定する元の探索への変更を見てみましょう。
g.V().in('created').has('name','Julia Child').count()
===>3
この変更した探索でも、すべての頂点が探索されますが、内向きエッジの巡回に際しては、createdというラベルが付けられたエッジに制限されます。次のプロファイルから、画像が改善されている様子がわかります。
gremlin> g.V().in('created').has('name','Julia Child').count().profile()
==>Traversal Metrics
Step                                                               Count  Traversers       Time (ms)    % Dur
=============================================================================================================
DsegGraphStep(vertex,[])                                              61          61          22.251    16.91
  query-optimizer                                                                              1.760
    \_condition=((label = FridgeSensor | label = author | label = book | label = ingredient | label = meal |
                label = recipe | label = reviewer) & (true))
  query-setup                                                                                  0.071
    \_isFitted=true
    \_isSorted=false
    \_isScan=true
  index-query                                                                                  1.139
    \_usesCache=false
    \_statement=SELECT "city_id", "sensor_id" FROM "DSEQuickStart"."FridgeSensor_p" WHERE "~~vertex_exists" =
                 ? LIMIT ? ALLOW FILTERING; with params (java.lang.Boolean) true, (java.lang.Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
  index-query                                                                                  2.012
    \_usesCache=false
    \_statement=SELECT "community_id", "member_id" FROM "DSEQuickStart"."author_p" WHERE "~~vertex_exists" =
                ? LIMIT ? ALLOW FILTERING; with params (java.lang.Boolean) true, (java.lang.Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
  index-query                                                                                  0.549
    \_usesCache=false
    \_statement=SELECT "community_id", "member_id" FROM "DSEQuickStart"."book_p" WHERE "~~vertex_exists" = ?
                LIMIT ? ALLOW FILTERING; with params (java.lang.Boolean) true, (java.lang.Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
  index-query                                                                                  0.849
    \_usesCache=false
    \_statement=SELECT "community_id", "member_id" FROM "DSEQuickStart"."ingredient_p" WHERE "~~vertex_exists
                " = ? LIMIT ? ALLOW FILTERING; with params (java.lang.Boolean) true, (java.lang.Integer) 5000
                0
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
  index-query                                                                                  0.887
    \_usesCache=false
    \_statement=SELECT "community_id", "member_id" FROM "DSEQuickStart"."meal_p" WHERE "~~vertex_exists" = ?
                LIMIT ? ALLOW FILTERING; with params (java.lang.Boolean) true, (java.lang.Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
  index-query                                                                                  0.889
    \_usesCache=false
    \_statement=SELECT "community_id", "member_id" FROM "DSEQuickStart"."recipe_p" WHERE "~~vertex_exists" =
                ? LIMIT ? ALLOW FILTERING; with params (java.lang.Boolean) true, (java.lang.Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
  index-query                                                                                  0.499
    \_usesCache=false
    \_statement=SELECT "community_id", "member_id" FROM "DSEQuickStart"."reviewer_p" WHERE "~~vertex_exists"
                = ? LIMIT ? ALLOW FILTERING; with params (java.lang.Boolean) true, (java.lang.Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
DsegVertexStep(IN,[created],vertex)                                    8           8         103.458    78.62
  query-optimizer                                                                              0.618
    \_condition=(((label = created) & (true)) & direction = IN)
  vertex-query                                                                                 0.261
    \_usesCache=false
    \_statement=SELECT * FROM "DSEQuickStart"."author_e" WHERE "community_id" = ? AND "member_id" = ? AND "~~
                edge_label_id" = ? LIMIT ? ALLOW FILTERING; with params (java.lang.Integer) 1432048000, (java
                .lang.Long) 1, (java.lang.Integer) 65577, (java.lang.Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
    \_isPartitioned=false
    \_usesIndex=false
  vertex-query                                                                                 0.200
    \_usesCache=false
    \_statement=SELECT * FROM "DSEQuickStart"."author_e" WHERE "community_id" = ? AND "member_id" = ? AND "~~
                edge_label_id" = ? LIMIT ? ALLOW FILTERING; with params (java.lang.Integer) 153541376, (java.
                lang.Long) 1, (java.lang.Integer) 65577, (java.lang.Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
    \_isPartitioned=false
    \_usesIndex=false
  query-setup                                                                                  0.017
    \_isFitted=true
    \_isSorted=true
    \_isScan=false
  vertex-query                                                                                 6.140
    \_usesCache=false
    \_statement=SELECT * FROM "DSEQuickStart"."author_e" WHERE "community_id" = ? AND "member_id" = ? AND "~~
                edge_label_id" = ? LIMIT ? ALLOW FILTERING; with params (java.lang.Integer) 588941056, (java.
                lang.Long) 0, (java.lang.Integer) 65577, (java.lang.Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
    \_isPartitioned=false
    \_usesIndex=false
  query-setup                                                                                  0.017
    \_isFitted=true
    \_isSorted=true
    \_isScan=false
  vertex-query                                                                                 0.201
    \_usesCache=false
    \_statement=SELECT * FROM "DSEQuickStart"."author_e" WHERE "community_id" = ? AND "member_id" = ? AND "~~
                edge_label_id" = ? LIMIT ? ALLOW FILTERING; with params (java.lang.Integer) 771301632, (java.
                lang.Long) 0, (java.lang.Integer) 65577, (java.lang.Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
    \_isPartitioned=false
    \_usesIndex=false
  query-setup                                                                                  0.012
    \_isFitted=true
    \_isSorted=true
    \_isScan=false
  vertex-query                                                                                 0.173
    \_usesCache=false
    \_statement=SELECT * FROM "DSEQuickStart"."author_e" WHERE "community_id" = ? AND "member_id" = ? AND "~~
                edge_label_id" = ? LIMIT ? ALLOW FILTERING; with params (java.lang.Integer) 994194304, (java.
                lang.Long) 0, (java.lang.Integer) 65577, (java.lang.Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
    \_isPartitioned=false
    \_usesIndex=false
  query-setup                                                                                  0.012
    \_isFitted=true
    \_isSorted=true
    \_isScan=false
NoOpBarrierStep(2500)                                                  8           4           0.910     0.69
HasStep([name.=(Julia Child)])                                         3           1           4.903     3.73
CountGlobalStep                                                        1           1           0.075     0.06
                                            >TOTAL                     -           -         131.599        -
2. Studioによる探索2のプロファイル出力

最初のステップでは、元の探索と同様にすべての頂点が検出されます。しかし、次のステップで、巡回されるエッジの数は大幅に減ります。ただし、プロダクション・グラフの場合、グラフ全体のすべての頂点を見つけるには時間がかかります。3番目のステップでは、Julia Childが創作したレシピの数に対する正答が反映されます。最初の探索では、Julia Childの本に対する他の内向きエッジがカウントに含まれています。

このグラフ探索は、依然として、すべての頂点を巡回するOLAP探索であり、インデックスを使用しません。

頂点ラベルの指定

頂点ラベルを指定することによって、探索改善にどのような影響があるでしょうか?
g.V().hasLabel('recipe').in().has('name','Julia Child').count()
===>3
この変更後の探索はrecipe頂点に制限されるようになりますが、すべての内向きエッジを巡回します。このプロファイルを見ると、画像がいくらか改善されている様子がわかります。
gremlin> g.V().hasLabel('recipe').in().has('name','Julia Child').count().profile()
==>Traversal Metrics
Step                                                               Count  Traversers       Time (ms)    % Dur
=============================================================================================================
DsegGraphStep([~label.=(recipe)])                                      8           8           2.598     9.25
  query-optimizer                                                                              0.241
    \_condition=((label = recipe) & (true))
  query-setup                                                                                  0.187
    \_isFitted=true
    \_isSorted=false
    \_isScan=true
  index-query                                                                                  1.225
    \_usesCache=false
    \_statement=SELECT "community_id", "member_id" FROM "DSEQuickStart"."recipe_p" WHERE "~~vertex_exists" =
                ? LIMIT ? ALLOW FILTERING; with params (java.lang.Boolean) true, (java.lang.Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
DsegVertexStep(IN,vertex)                                             15          15           9.668    34.41
  query-optimizer                                                                              0.150
    \_condition=((true) & direction = IN)
  query-setup                                                                                  0.047
    \_isFitted=false
    \_isSorted=true
    \_isScan=false
  vertex-query                                                                                 0.896
    \_usesCache=false
    \_statement=SELECT * FROM "DSEQuickStart"."recipe_e" WHERE "community_id" = ? AND "member_id" = ? LIMIT ?
                 ALLOW FILTERING; with params (java.lang.Integer) 1315507840, (java.lang.Long) 1, (java.lang.
                Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
    \_isPartitioned=false
    \_usesIndex=false
  vertex-query                                                                                 1.415
    \_usesCache=false
    \_statement=SELECT * FROM "DSEQuickStart"."recipe_e" WHERE "community_id" = ? AND "member_id" = ? LIMIT ?
                 ALLOW FILTERING; with params (java.lang.Integer) 96517120, (java.lang.Long) 1, (java.lang.In
                teger) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
    \_isPartitioned=false
    \_usesIndex=false
  vertex-query                                                                                 2.846
    \_usesCache=false
    \_statement=SELECT * FROM "DSEQuickStart"."recipe_e" WHERE "community_id" = ? AND "member_id" = ? LIMIT ?
                 ALLOW FILTERING; with params (java.lang.Integer) 1598713728, (java.lang.Long) 1, (java.lang.
                Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
    \_isPartitioned=false
    \_usesIndex=false
  query-setup                                                                                  0.038
    \_isFitted=false
    \_isSorted=true
    \_isScan=false
  vertex-query                                                                                 0.364
    \_usesCache=false
    \_statement=SELECT * FROM "DSEQuickStart"."recipe_e" WHERE "community_id" = ? AND "member_id" = ? LIMIT ?
                 ALLOW FILTERING; with params (java.lang.Integer) 1146421632, (java.lang.Long) 1, (java.lang.
                Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
    \_isPartitioned=false
    \_usesIndex=false
  query-setup                                                                                  0.014
    \_isFitted=false
    \_isSorted=true
    \_isScan=false
  vertex-query                                                                                 0.431
    \_usesCache=false
    \_statement=SELECT * FROM "DSEQuickStart"."recipe_e" WHERE "community_id" = ? AND "member_id" = ? LIMIT ?
                 ALLOW FILTERING; with params (java.lang.Integer) 384373760, (java.lang.Long) 2, (java.lang.I
                nteger) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
    \_isPartitioned=false
    \_usesIndex=false
  query-setup                                                                                  0.014
    \_isFitted=false
    \_isSorted=true
    \_isScan=false
HasStep([name.=(Julia Child)])                                         3           3          15.765    56.10
CountGlobalStep                                                        1           1           0.068     0.24
                                            >TOTAL                     -           -          28.100        -
3. Studioによる探索3のプロファイル出力

最初のステップで検出される頂点の数は限られており、多数のエッジが巡回されました。ただしプロダクション・グラフでは、インデックスを使用しないと、限られた数の頂点の探索であっても時間がかかり、また、巡回されるエッジの数も膨大になる可能性があります。

このグラフ探索は、依然として、インデックス作成を使用しないOLAP探索です。この探索は、まず、頂点ラベルを制限することによってクエリーを絞り込みますが、探索の開始点の検出にインデックスは使用されません。

エッジ・ラベルと頂点ラベルの使用

インデックスは、頂点ラベルとプロパティ・キーによって識別されます。次のグラフ探索では、クエリーの方向が変更されています。
g.V().has('author', 'name', 'Julia Child').outE('created').count()
===>3
頂点ラベルauthorおよび具体的なプロパティ・キーの両方と値Julia Childを指定することによって、この探索は1つの頂点から開始され、エッジ・ラベルcreatedを持つ外向きエッジのみを巡回します。
gremlin> g.V().has('author','name','Julia Child').outE('created').count().profile()
==>Traversal Metrics
Step                                                               Count  Traversers       Time (ms)    % Dur
=============================================================================================================
DsegGraphStep([~label.=(author), name.=(Julia C...                     1           1          29.049    84.45
  query-optimizer                                                                              7.673
    \_condition=(((label = author) & (true)) & name = Julia Child)
  query-setup                                                                                  0.033
    \_isFitted=true
    \_isSorted=false
    \_isScan=false
  index-query                                                                                 17.694
    \_indexType=Secondary
    \_usesCache=false
    \_statement=SELECT "community_id", "member_id" FROM "DSEQuickStart"."author_p" WHERE "name" = ? LIMIT ?;
                with params (java.lang.String) Julia Child, (java.lang.Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
DsegVertexStep(OUT,[created],edge)                                     3           3           5.265    15.31
  query-optimizer                                                                              0.200
    \_condition=(((label = created) & (true)) & direction = OUT)
  vertex-query                                                                                 0.586
    \_usesCache=false
    \_statement=SELECT * FROM "DSEQuickStart"."author_e" WHERE "community_id" = ? AND "member_id" = ? AND "~~
                edge_label_id" = ? LIMIT ? ALLOW FILTERING; with params (java.lang.Integer) 1535517312, (java
                .lang.Long) 0, (java.lang.Integer) 65576, (java.lang.Integer) 50000
    \_options=Options{consistency=Optional[ONE], serialConsistency=Optional.empty, fallbackConsistency=Option
              al.empty, pagingState=null, pageSize=-1, user=Optional.empty, waitForSchemaAgreement=true, asyn
              c=true}
    \_isPartitioned=false
    \_usesIndex=false
  query-setup                                                                                  0.057
    \_isFitted=true
    \_isSorted=true
    \_isScan=false
CountGlobalStep                                                        1           1           0.081     0.24
                                            >TOTAL                     -           -          34.397        -
4. Studioによる探索4のプロファイル出力

単一の頂点から探索が開始されます。エッジ・ラベルによりエッジがフィルター処理されます。

このグラフ探索はOLTP探索です。頂点ラベルauthorおよびプロパティ・キーnameに対するインデックスを使用すると、インデックスが付けられた頂点から探索を直接開始できます。この例の結果は単一の頂点ですが、インデックス作成を使用して開始点を複数の頂点に制限するクエリーは、グラフ内のすべての頂点をチェックしなければならない線形スキャンよりも効率的です。したがって、サブグラフ(グラフの一部)を探索します。

OLTPグラフ探索を作成する際に重要なことは、グラフの探索方法を検討することです。インデックス作成の使用は、トランザクション処理を高速で行ううえで不可欠です。DSE Graphに付属しているプロファイリング・ツールは、探索のパフォーマンスの分析に役立ちます。

Sparkを使用したOLAPクエリーの実行については、「DSE GraphおよびGraph Analytics」を参照してください。