オンラインで優れたリソースを見つけることができなかったので、さらに実践的な調査を行い、その調査に基づいて実装している結果のフルテキストメンテナンスプランを投稿すると役立つと思いました。
メンテナンスが必要な時期を判断するためのヒューリスティック
私たちの主な目標は、基礎となるテーブルでデータが進化しても、一貫したフルテキストクエリのパフォーマンスを維持することです。ただし、さまざまな理由により、各データベースに対してフルテキストクエリの代表的なスイートを毎晩起動し、それらのクエリのパフォーマンスを使用してメンテナンスが必要な時期を判断することは困難です。そのため、非常に迅速に計算でき、フルテキストインデックスのメンテナンスが必要であることを示すためのヒューリスティックとして使用できる経験則を作成しようとしていました。
この調査の過程で、システムカタログは、フルテキストインデックスがどのようにフラグメントに分割されているかに関する多くの情報を提供することがわかりました。ただし、sys.dm_db_index_physical_statsを介したbツリーインデックスの場合と同様に、公式の「断片化%」は計算されません。フルテキストフラグメント情報に基づいて、独自の「フルテキストフラグメント化%」を計算することにしました。次に、開発サーバーを使用して、100〜25,000行のランダムな更新を繰り返し実行し、実稼働データの1,000万行のコピーを作成し、フルテキストの断片化を記録し、を使用してベンチマークフルテキストクエリを実行しましたCONTAINSTABLE
。
上下のグラフに見られるように、結果は非常に明るく、作成したフラグメンテーション測定値が、観測されたパフォーマンスと非常に高い相関があることを示しました。これは本番環境での定性的観察とも結びついているため、フルテキストインデックスのメンテナンスが必要な時期を判断するためのヒューリスティックとして断片化%を使用しても十分です。
メンテナンス計画
次のコードを使用して、各フルテキストインデックスの断片化%を計算することにしました。断片化が少なくとも10%ある重要なサイズのフルテキストインデックスは、一晩のメンテナンスによって再構築されるようにフラグが立てられます。
-- Compute fragmentation information for all full-text indexes on the database
SELECT c.fulltext_catalog_id, c.name AS fulltext_catalog_name, i.change_tracking_state,
i.object_id, OBJECT_SCHEMA_NAME(i.object_id) + '.' + OBJECT_NAME(i.object_id) AS object_name,
f.num_fragments, f.fulltext_mb, f.largest_fragment_mb,
100.0 * (f.fulltext_mb - f.largest_fragment_mb) / NULLIF(f.fulltext_mb, 0) AS fulltext_fragmentation_in_percent
INTO #fulltextFragmentationDetails
FROM sys.fulltext_catalogs c
JOIN sys.fulltext_indexes i
ON i.fulltext_catalog_id = c.fulltext_catalog_id
JOIN (
-- Compute fragment data for each table with a full-text index
SELECT table_id,
COUNT(*) AS num_fragments,
CONVERT(DECIMAL(9,2), SUM(data_size/(1024.*1024.))) AS fulltext_mb,
CONVERT(DECIMAL(9,2), MAX(data_size/(1024.*1024.))) AS largest_fragment_mb
FROM sys.fulltext_index_fragments
GROUP BY table_id
) f
ON f.table_id = i.object_id
-- Apply a basic heuristic to determine any full-text indexes that are "too fragmented"
-- We have chosen the 10% threshold based on performance benchmarking on our own data
-- Our over-night maintenance will then drop and re-create any such indexes
SELECT *
FROM #fulltextFragmentationDetails
WHERE fulltext_fragmentation_in_percent >= 10
AND fulltext_mb >= 1 -- No need to bother with indexes of trivial size
これらのクエリでは次のような結果が得られます。この場合、フルテキストインデックスが1MBを超えており、少なくとも10%断片化されているため、行1、6、および9は最適なパフォーマンスには断片化が多すぎるとマークされます。
メンテナンスケイデンス
すでに夜間のメンテナンスウィンドウがあり、断片化の計算は非常に安価です。そのため、このチェックを毎晩実行し、10%の断片化しきい値に基づいて、必要に応じてフルテキストインデックスを実際に再構築するより高価な操作のみを実行します。
再構築対再編成対ドロップ/作成
SQL ServerはオプションREBUILD
とREORGANIZE
オプションを提供しますが、それらは完全なフルテキストカタログ(フルテキストインデックスをいくつでも含むことができます)でのみ使用できます。レガシーの理由により、すべてのフルテキストインデックスを含む単一のフルテキストカタログがあります。そのため、代わりに個々のフルテキストインデックスレベルで削除(DROP FULLTEXT INDEX
)してから再作成(CREATE FULLTEXT INDEX
)することを選択しました。
フルテキストインデックスを論理的な方法で個別のカタログに分割し、REBUILD
代わりに実行する方が理想的かもしれませんが、その間にドロップ/作成ソリューションが機能します。