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
この探索で、次の処理が完了します。
- すべての頂点を見る。
- 内向きエッジを巡回する。
Julia Child
のname
とプロパティ値のプロパティ・キーを持つ隣接する頂点を検索します。- 頂点の数をカウントします。
このグラフ探索は典型的なOLAP探索です。この探索では、すべての頂点にタッチする必要があり、インデックスを使用しません。返されるカウントには、レシピだけでなくJulia Childに対するエッジを持つ頂点がすべて含まれます。後で説明しますが、カウント数は不正確で非常に大きくなります。
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コマンドが含まれています。最初のステップを見ると、グラフ内のすべての頂点が探索されています。このグラフは非常に小規模なため、頂点の数は、プロダクション・グラフと比べて無視できます。次のステップでは、頂点に入ってくるすべてのエッジを検出する必要があります。繰り返しになりますが、小規模なグラフの場合、エッジの数はごく少数ですが、プロダクション・グラフのエッジ数は数百万から数十億になります。ここでは、隣接頂点をフィルター処理して頂点の数を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 -
最初のステップでは、元の探索と同様にすべての頂点が検出されます。しかし、次のステップで、巡回されるエッジの数は大幅に減ります。ただし、プロダクション・グラフの場合、グラフ全体のすべての頂点を見つけるには時間がかかります。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 -
最初のステップで検出される頂点の数は限られており、多数のエッジが巡回されました。ただしプロダクション・グラフでは、インデックスを使用しないと、限られた数の頂点の探索であっても時間がかかり、また、巡回されるエッジの数も膨大になる可能性があります。
このグラフ探索は、依然として、インデックス作成を使用しない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 -
単一の頂点から探索が開始されます。エッジ・ラベルによりエッジがフィルター処理されます。
このグラフ探索はOLTP探索です。頂点ラベルauthor
およびプロパティ・キーname
に対するインデックスを使用すると、インデックスが付けられた頂点から探索を直接開始できます。この例の結果は単一の頂点ですが、インデックス作成を使用して開始点を複数の頂点に制限するクエリーは、グラフ内のすべての頂点をチェックしなければならない線形スキャンよりも効率的です。したがって、サブグラフ(グラフの一部)を探索します。
OLTPグラフ探索を作成する際に重要なことは、グラフの探索方法を検討することです。インデックス作成の使用は、トランザクション処理を高速で行ううえで不可欠です。DSE Graphに付属しているプロファイリング・ツールは、探索のパフォーマンスの分析に役立ちます。
Sparkを使用したOLAPクエリーの実行については、「DSE GraphおよびGraph Analytics」を参照してください。