Graphのアンチパターン
DSE Graphでよくある間違いを検証します。
DSE Graphでは、よくある間違いがいくつかあります。ベスト・プラクティスを検討することで、学習のハードルを下げるとともに、グラフ・アプリケーションのパフォーマンスを改善することができます。
インデックス作成を使用しない
g.V().has('name','James Beard')...
プロパティ・キーname
を使用しているすべての頂点をチェックするように探索で指定する必要があります。このクエリーを次のように変更すると、g.V().has('author', 'name', 'James Beard')...
クエリーで著者レコードのすべての名前について作成可能なインデックスを参照し、頂点を1つだけ取得して探索を開始できます。インデックスはスキーマ作成時に追加されます。schema.vertexLabel('author').index('byName').secondary().by('name').add()
つまり、探索でこのような変更を行った場合、クエリーはOLAPクエリーからOLTPクエリーへと変更されます。
プロパティ・キーの作成
schema.propertyKey('recipeCreationDate').Timestamp().create()
schema.propertyKey('mealCreationDate').Timestamp().create()
schema.propertyKey('reviewCreationDate').Timestamp().create()
このプロパティ・キー名だとコードが読みやすく、グラフ探索での追跡が簡単になりますが、保存されている追加のプロパティ・キーごとにリソースが必要です。代わりに、次のようなプロパティ・キーを1つ使用すると、schema.propertyKey('timestamp').Timestamp().create()
オーバーヘッドを減らすことができます。グラフ探索では、プロパティ・キーは主に頂点ラベルと一緒に使用されるため、timestamp
は、頂点ラベルとプロパティ・キーの組み合わせによって一意に識別されます。頂点ラベルの作成
schema.vertexLabel('recipeAuthor').create()
schema.vertexLabel('bookAuthor').create()
schema.vertexLabel('mealAuthor').create()
schema.vertexLabel('reviewAuthor').create()
前述したように、このような頂点ラベルは読みやすいという利点がありますが、頂点ラベルに対して一意にクエリーを行わないのであれば、この機能を単一の頂点ラベルにまとめた方が得策です。たとえば、上記のコードでは、「recipes」、「meals」、「books」の作成者が同じ可能性がある一方、「reviews」にはさまざまな著者とクエリーのタイプが存在する可能性があります。次のように、頂点ラベルは4つではなく2つ使用してください。schema.vertexLabel('author').create()
schema.vertexLabel('reviewer').create()
実際のところ、この場合は、作成者およびレビュー担当者の重複が十分に大きければ、頂点ラベルperson
を1つだけ使用する方が適しているかもしれません。場合によっては、person
が作成者かレビュー担当者かを識別するプロパティ・キーが有効な選択肢となります。schema.propertyKey('type').Text().create()
schema.vertexLabel('person').create()
graph.addVertex(label, 'person', 'type', 'author', 'name', 'Jamie Oliver')
スキーマ作成または構成設定と探索クエリーの混在
read vertex
のname
フィールドに対してカウントを実行します。schema.config().option('graph.tx_groups.default.read_consistency').set('ALL');
g.V().has('name', 'read vertex').count()
Gremlin Serverでは、1つのトランザクションで両方の文が実行されます。このトランザクションの実行中に行われた変更は、両方のアクションが正常にコミットされた場合に適用されます。読み取り整合性の変更は、トランザクションが終了されるまで実際には適用されません。したがって、この変更は、次のトランザクションで初めて有効になります。これらの文は、個別のリクエストとして順次処理されることはありません。処理中にこのようなエラーが発生しないようにするには、アプリケーション内で、スキーマ作成または構成設定と探索クエリーを混在させないでください。グラフ探索でグラフ・データベースに対してクエリーを実行する前に、スキーマを作成して構成を行っておくことがベスト・プラクティスです。
OLTPクエリーの実行時間が長すぎることを示すInterruptedException
一般的に、この例外がログに記録されていた場合は、OLTPクエリーの実行時間が長すぎることを意味します。典型的な原因としては、グラフ探索クエリーで使用する要素のインデックスが作成されていないことが挙げられます。インデックスを作成してクエリーを再試行してください。
g.V().count()およびg.E().count()は長い遅延を引き起こす可能性がある
大規模なグラフでカウントを実行すると、重大な問題が発生することがあります。基本的に、コマンドはすべての頂点で繰り返す必要があるため、グラフが大きい場合は何時間もかかります。どのテーブル・スキャン(すべての頂点の繰り返し)もOLTPプロセスではありません。エッジで同じプロセスを実行することも実質的に同じです。つまり、すべてのテーブルがスキャンされます。現時点で、これらのカウントを得るには、Sparkコマンドを使用する方法が推奨されます。
graph_name_systemに対して低すぎるレプリケーション係数を設定する
作成された各グラフは、graph_name、graph_name_system、およびgraph_name_pvtの3つのDSEデータベース・キースペースを作成します。graph_name_systemはグラフ・スキーマを格納しており、このデータを喪失するとグラフ全体が動作不能になります。クラスター構成に基づいて適切なレプリケーション係数を設定してください。
パラメーター化されたクエリーではなく文字列連結をアプリケーションで使用する
グラフ・アプリケーションでの文字列連結は、パフォーマンスを大幅に低下させます。一意な各クエリー文字列はノードでキャッシュされるオブジェクトを作成し、ノードのリソースを使い果たします。リソース割り当てに起因する問題を防ぐには、パラメーター化されたクエリー(DSE Javaドライバー、DSE Pythonドライバー、DSE Rubyドライバー、DSE Node.jsドライバー、DSE C#ドライバー、DSE C/C++ドライバー)を使用してください。