フルテキスト インデックスの構造
フルテキスト インデックスの構造をよく理解しておくことは、Full-Text Engine の動作を理解するのに役立ちます。このトピックでは、Adventure Works の Document テーブルの抜粋をテーブル例として使用します。この抜粋には、テーブルの 2 つの列 (DocumentID 列および Title 列) と 3 つの行のみが含まれています。
注意 |
---|
このサンプル テーブルの列に関する詳細については、「Document テーブル (AdventureWorks)」を参照してください。 |
この例では、Title 列に対してフルテキスト インデックスが作成されているものとします。
DocumentID |
Title |
---|---|
1 |
Crank Arm and Tire Maintenance |
2 |
Front Reflector Bracket and Reflector Assembly 3 |
3 |
Front Reflector Bracket Installation |
たとえば、次のテーブル (フラグメント 1) は、Document テーブルの Title 列に対して作成されたフルテキスト インデックスの内容を示しています。フルテキスト インデックスには、この表に示されているより多くの情報が含まれています。このテーブルは、フルテキスト インデックスの論理表現であり、例を挙げる目的で紹介しています。行は、ディスクの使用量を最適化するために圧縮形式で格納されます。
データが元のドキュメントとは逆になっていることに注意してください。これはキーワードがドキュメント ID にマップされているためです。このため、フルテキスト インデックスは一般に逆インデックスと呼ばれます。
キーワード "and" がフルテキスト インデックスから削除されていることにも注意してください。これは "and" がストップ ワードであり、フルテキスト インデックスからストップ ワードを削除することで、ディスク領域を大幅に節約し、クエリのパフォーマンスを向上させることができるためです。ストップ ワードの詳細については、「ストップ ワードとストップ リスト」を参照してください。
フラグメント 1
Keyword |
ColId |
DocId |
Occurrence |
---|---|---|---|
Crank |
1 |
1 |
1 |
Arm |
1 |
1 |
2 |
Tire |
1 |
1 |
4 |
Maintenance |
1 |
1 |
5 |
Front |
1 |
2 |
1 |
Front |
1 |
3 |
1 |
Reflector |
1 |
2 |
2 |
Reflector |
1 |
2 |
5 |
Reflector |
1 |
3 |
2 |
Bracket |
1 |
2 |
3 |
Bracket |
1 |
3 |
3 |
Assembly |
1 |
2 |
6 |
3 |
1 |
2 |
7 |
Installation |
1 |
3 |
4 |
Keyword 列には、インデックス作成時に抽出された単一のトークン表現が含まれています。ワード ブレーカが、トークンの構成要素を決定します。
ColId 列には、フルテキスト インデックスが作成されている特定の列に対応する値が含まれています。
DocId 列には、フルテキスト インデックスが作成されているテーブルで特定のフルテキスト キー値にマップされる 8 バイトの整数値が含まれています。このマッピングは、フルテキスト キーが整数データ型でない場合に必要になります。このような場合、フルテキスト キー値と DocId 値とのマッピングは、DocId Mapping テーブルと呼ばれる別のテーブルで保持されます。これらのマッピングをクエリするには、sp_fulltext_keymappings システム ストアド プロシージャを使用します。検索条件を満たすには、上記の表の DocId 値と DocId Mapping テーブルを結合し、クエリ対象のベース テーブルから行を取得する必要があります。ベース テーブルのフルテキスト キー値が整数データ型の場合は、その値を DocId として直接使用できるため、マッピングは必要ありません。したがって、整数データ型のフルテキスト キー値を使用すると、フルテキスト クエリを最適化できます。
Occurrence 列には整数値が含まれます。DocId 値ごとに、その DocId 内の特定キーワードの相対的な単語オフセットに対応するオカレンス値の一覧があります。オカレンス値は、句または近接検索の判定に役立ちます。たとえば、句には数値の近いオカレンス値が含まれます。また、関連性スコアを計算するのにも役立ちます。たとえば、DocId のキーワードのオカレンス数をスコアリングに使用できます。
フルテキスト インデックス フラグメント
論理フルテキスト インデックスは、通常、複数の内部テーブルに分割されます。各内部テーブルは、フルテキスト インデックス フラグメントと呼ばれます。これらのフラグメントの一部は、他のフラグメントよりも新しいデータを含んでいることがあります。たとえば、DocId が 3 である次の行をユーザーが更新し、テーブルの変更が自動的に追跡される場合、新しいフラグメントが作成されます。
DocumentID |
Title |
---|---|
3 |
Rear Reflector |
次に示すフラグメント 2 には、フラグメント 1 より新しい、DocId 3 に関するデータが含まれています。したがって、ユーザーが "Rear Reflector" をクエリした場合、フラグメント 2 に含まれている DocId 3 のデータが使用されます。各フラグメントには、sys.fulltext_index_fragments カタログ ビューを使用してクエリできる作成タイムスタンプが付いています。
フラグメント 2
Keyword |
ColId |
DocId |
Occ |
---|---|---|---|
Rear |
1 |
3 |
1 |
Reflector |
1 |
3 |
2 |
フラグメント 2 を見ればわかるように、フルテキスト クエリでは、各フラグメントを内部的にクエリし、古いエントリを破棄する必要があります。したがって、非常に多くのフルテキスト インデックス フラグメントがフルテキスト インデックスに含まれている場合、クエリのパフォーマンスが大幅に低下する可能性があります。フラグメントの数を減らすには、ALTER FULLTEXT CATALOGTransact-SQL ステートメントの REORGANIZE オプションを使用してフルテキスト カタログを再構成します。このステートメントはマスタ マージを実行します。マスタ マージでは、フラグメントが単一のより大きなフラグメントにマージされ、フルテキスト インデックスから古いエントリがすべて削除されます。
再構成が完了すると、次の行が例のインデックスに格納されます。
Keyword |
ColId |
DocId |
Occ |
---|---|---|---|
Crank |
1 |
1 |
1 |
Arm |
1 |
1 |
2 |
Tire |
1 |
1 |
4 |
Maintenance |
1 |
1 |
5 |
Front |
1 |
2 |
1 |
Rear |
1 |
3 |
1 |
Reflector |
1 |
2 |
2 |
Reflector |
1 |
2 |
5 |
Reflector |
1 |
3 |
2 |
Bracket |
1 |
2 |
3 |
Assembly |
1 |
2 |
6 |
3 |
1 |
2 |
7 |