インデックス作成

インデックスとそれがDSE Graphのパフォーマンスに与える影響について説明します。

インデックスは、DSE Graphクエリーのパフォーマンスを向上させる上で重要な役割を果たします。情報を見つけるためにグラフ全体を探索する必要があるGraphクエリーはパフォーマンスに悪影響を与えるため、プロダクション環境ではフル・スキャン・クエリーは許可されていません。インデックス作成により、最初の探索を開始する頂点と、この開始点から探索するエッジと頂点の絞り込みという、グラフのクエリーの2つの側面を改善することができます。DSE Graphは、クエリー処理のこれらの異なる側面に対処するために、グローバル・インデックスと頂点中心インデックス(VCI)という2種類のインデックスを実装しています。グローバル・インデックスは、クエリーの開始点を見つけるために使用され、頂点プロパティの値に一致する値を見つける機能を果たします。頂点中心インデックスは、開始点が定義された後、クエリーの対象範囲を絞り込むために使用されます。

グローバル・インデックスの概要

グローバル・インデックスは、頂点ラベルプロパティを使用して、グラフ探索クエリーの開始点を識別します。グラフ・クエリーは、エッジではなく頂点から開始する必要があることを理解することが重要です。エッジ・プロパティを使用している頂点中心インデックスを使用して探索を絞り込むことは可能ですが、探索をエッジから開始することはできません。DSE Graphなどの分散グラフ・データベースでは、Julia Childの頂点IDを使用する次のクエリーのように、頂点IDで識別される頂点から始まるのが、最も効率的な探索です。
g.V(['~label':'person', 'personId':1])
ただし、頂点IDで頂点を識別することは、制限が大きくなります。探索で頂点ラベルとプロパティを使用すると、DSE Graphは、すべてのDSEノードからすべてのデータを読み取ることなく、頂点データが存在するDSEノードを識別することができます。ほとんどのグラフ・クエリーは、最初にグローバル・インデックスを使用して、よりわかりやすいプロパティを持つ開始頂点を見つけます。
g.V().has('person', 'name', 'Julia Child')
nameプロパティは頂点IDの一部ではないため、検索条件を正しい頂点と一致させるには、インデックスが必要で、そのインデックスはグローバル・インデックスです。

DSE Graphのグローバルインデックスは、マテリアライズド・ビュー(MV)検索インデックス、またはセカンダリ・インデックスの3つのDSEインデックス付けのいずれかの方法で実現できます。

マテリアライズド・ビューとは、ベース・テーブル以外のプライマリ・キーに基づくクエリーを提供するためにベース・テーブルから生成されるテーブルのことです。このタイプのインデックスは、ほぼ一意の値のカーディナリティが高い、つまりセレクティビティが高い値での使用に適しています。セレクティビティは、次の式を使用してカーディナリティから導き出されます。
selectivity = ( cardinality / number of rows ) * 100%
一般的に、カーディナリティが低いとセレクティビティも低くなり、カーディナリティが高いとセレクティビティも高くなります。マテリアライズド・ビューの検索では、データの書き込みによって多少のタイム・ペナルティーが生じますが、レスポンス・タイムはベース・テーブルの検索と同様です。データの書き込みまたは更新がグラフで行われると、グラフ・テーブルとともにMVテーブルでもインデックス情報が更新されます。MVテーブルを使用すると、書き込みレイテンシーが高くなりますが、グラフ探索の読み取りレイテンシーは低くなります。

検索インデックスは、テキスト、数値、地理空間の各インデックスが必要な場合に使用され、DSE Searchに依存します。グラフ・データはDSEデータベース・テーブルに格納されるため、頂点ラベルあたり1個の検索コアを使用可能です。検索でインデックス作成される頂点ラベルごとに、searchという名前の単一の検索インデックスにすべてのプロパティを追加する必要があります。検索はDSE Searchで実装されているため、すべてのデータ型のインデックスを作成できます。全文と文字列という2つのインデックス・オプションでは、インデックス作成結果が異なるため、プロパティ・キーを定義する必要があります。全文インデックスでは、トークン化とセカンダリ・プロセス(大文字・小文字の正規化など)が実行されます。全文インデックスは、テキストの部分一致が必要なクエリーで使用でき、正規表現(regEx)検索に役立ちます。文字列インデックスは、Solrファセット化と似ており、文字列の完全一致が求められ、トークン化が必要とならないクエリーで使用されます。このタイプのインデックスは、セレクティビティが低い場合に最適ですが、トークン化インデックスと非トークン化インデックスの両方であいまい一致に役立ちます。

DSE Graphのセカンダリ・インデックスは、DSEセカンダリ・インデックスと同じ法則に従います。このタイプのインデックスは、カーディナリティの低い値またはセレクティビティの低い値を対象としています。インデックス作成対象の値の数は、数十個から最大で数百個までに収まるべきです。たとえば、国で検索する操作は、セカンダリ・インデックスを使用するのに好適な例です。また、値の照合には等価条件しか使用できず、並べ替えまたは範囲クエリーを値に対して使用することはできません。より複雑な値の照合が必要な場合は、検索インデックスの方が優れた選択肢です。

グローバル・インデックスを要約するには:
インデックスの種類 用途
マテリアライズド・ビュー カーディナリティが高く、セレクティビティが高い頂点プロパティ、および等式述語で最も効率的なインデックス。
セカンダリ・インデックス カーディナリティが低く、セレクティビティが低い頂点プロパティ、および等式述語で効率的なインデックス。
検索インデックス

カーディナリティとセレクティビティの範囲が広い頂点プロパティに対して効率的で汎用性の高いインデックス。検索インデックスは、さまざまな述語をサポートしています。

  • 全文検索と文字列検索

  • ファジー検索(トークン化と非トークン化の両方)

  • 句の検索

  • 空間(地理空間、デカルト)検索

複合インデックス・キーは、現時点ではDSE Graphでサポートされていません。

頂点中心インデックス(VCI)の概要

頂点中心インデックス(VCI)は、追加のプロパティに基づいて探索を絞り込むために使用されます。フィルター後の頂点のサブセットに適用されるVCIと異なり、グローバル・インデックスは、指定された頂点ラベルを持つすべての頂点に適用されます。頂点中心インデックスは、ビッグO表記を使用して、O(n)からO(1)またはO(log n)までの探索の複雑さを軽減するときに特に重要です。VCIには、エッジ・インデックスとプロパティ・インデックスの2種類があります。これは、インシデント・エッジが多く存在する場合にすべてのインシデント・エッジを探索すると、探索のコストが急増するため、エッジ・インデックスは、頂点の全インシデント・エッジが線形スキャンされるのを防ぐために、関連するプロパティに基づいてエッジを探索するときに役立ちます。たとえば、エッジ・インデックスは、グローバル・インデックスが特定の頂点(この場合はJulia Child)で探索を開始したときに、特定のエッジだけを選択するのに役立ちます。
g.V().has('person', 'name', 'Julia Child').outE('created').has('createDate', gt(1960-01-01)) 
プロパティ・インデックスは、 メタプロパティにインデックスを付けるために作成されます。プロパティ・インデックスは、等式と不等式の両方の述語をサポートでき、クエリーによって値の範囲を返す必要がある場合に役立ちます。この例では、Fritz Streiffが住んでいたすべての国を検索し、その国に住み始めた年の順に並べます。
g.V().has('person', 'name', 'Fritz Streiff').properties('country').has('startYear', order().by(decr))

DSE Graphの頂点中心インデックスは、エッジ・インデックスとプロパティ・インデックスの両方のマテリアライズド・ビュー(MV)で実現され、グローバル・インデックスについて前述したプロパティと同じプロパティがあります。

インデックス作成のベスト・プラクティス

注意すべき最も重要なことは、クエリーの開始点を定義する2つ以上のプロパティのインデックスを作成するときの唯一の選択肢が検索インデックスであることです。複数のマテリアライズド・ビューまたはセカンダリ・インデックスをグローバル・インデックス作成に使用することはできません。たとえば、インデックスがマテリアライズド・ビューまたはセカンダリ・インデックスの場合、g.V().has('person', 'gender', 'F').has('person', 'country', 'France')は、両方のインデックスではなく、1つのインデックスのみを使用します。検索インデックスが定義されている場合、countrygenderの両方のプロパティが使用されます。開始点が定義されると、頂点中心インデックスを使用してクエリーを絞り込むことができます。

同一プロパティに関して複数のインデックスを作成できます。たとえば、マテリアライズド・ビュー(MV)インデックスと検索インデックスの両方をプロパティamountに関して作成できます。DSE Graphのクエリー最適化ツールは、クエリーの処理時に適切なインデックスを自動的に使用します。使用するインデックス・タイプを指定する機能はありません。パフォーマンスを最大限に高めるため、DSE Graphでは、MVインデックス、セカンダリ・インデックス、DSE Searchインデックスの優先順位で使用されます。ただし、最適なタイプのインデックスを選択することは、パフォーマンスを向上させる決め手となります。たとえば、マテリアライズド・ビューの制約を理解し、その理解に基づいてMVインデックスの数を決定することが重要です。「マテリアライズド・ビューについて」を参照してください。セレクティビティに基づいて、プロパティごとに異なるインデックス・タイプを適宜作成できます。一般的に、DSEでの全般的な使用が制限されているのと同じ理由で、DSE Graphのセカンダリ・インデックスは有用性が限られています。テキスト検索が必要で、検索インデックスが選択されている場合を除き、最初に、マテリアライズド・ビュー・インデックスを作成する必要があります。

検索インデックスが作成される場合は、インデックスの構築に時間がかかることと、インデックスが使用可能になるまでは、インデックスに依存するクエリーが失敗する可能性があることに注意してください。検索インデックスを必要とするデータ挿入をスキーマ作成の直後に行うと、アプリケーションでエラーが発生する場合があります。また、検索インデックスを使用するクエリーは、クラスター内のDSE Search対応ノードで実行する必要があります。また、検索インデックスには多くのリソースが必要です。インデックスごとにデフォルトで最小でも256MBのメモリーが割り当てられ、インデックスごとに2つの物理コアが必要となります。典型的な32GBノードの場合、検索インデックスの合理的な作成数は16個です。

テキスト述語(regex、tokenRegex、prefix、tokenPrefix、token、eq/neq)を使用するクエリーは、DSE Searchインデックスがないと実行できません。ただし、そのようなクエリーではセカンダリ・インデックスやマテリアライズド・インデックスが使用されず、代わりにフル・グラフ・スキャンを使用して結果が返されます。デフォルトで、プロダクション・モードではフル・グラフ・スキャンを実行できないため、そのようなクエリーは失敗します。このような照合検索方法が必要な場合は、検索インデックスを使用することが強く推奨されます。
注意: tokenRegexは、検索インデックスが使用されるかどうかにかかわらず、クエリーで大文字・小文字を区別しません。

トークン化(TextField)形式と非トークン化(StrField)形式の両方でテキスト検索インデックスがデフォルトで作成されます。つまり、インデックスが作成されたすべてのテキスト頂点プロパティでどのテキスト述語(token、tokenPrefix、tokenRegex、eq、neq、regex、prefix)でも使用できます。実際的には、asString()メソッドを使用して検索インデックスを作成する必要があるのは、在庫カテゴリ(食卓用金物、靴、衣服)など、トークン化とテキスト解析が絶対に役に立たない場合だけです。複数の文章から成る長い記述など、トークン化されたテキストの検索には、asText()メソッドが役に立ちます。クエリー最適化ツールは、使用されているテキスト述語に基づいて、解析済みインデックスと未解析インデックスのどちらを使用するかを選択します。

検索インデックス・スキーマを編集して、検索特性を変更することが可能です。これらの二次的な変更はDSE Graphによって上書きされませんが、この方法でフィールドの追加または削除は行わず、DSE Graphコマンドのみを使用してください。この機能の一般的な用途は、検索のタイプに大文字・小文字の区別を追加するなど、検索の動作を変更することです。