都内で働くSEの技術的なひとりごと / Technical soliloquy of System Engineer working in Tokyo

都内でサラリーマンやってます。SQL Server を中心とした (2023年からは Azure も。) マイクロソフト系(たまに、OSS系などマイクロソフト以外の技術も...)の技術的なことについて書いています。日々の仕事の中で、気になったことを技術要素関係なく気まぐれに選んでいるので記事内容は開発言語、インフラ等ばらばらです。なお、当ブログで発信、発言は私個人のものであり、所属する組織、企業、団体等とは何のかかわりもございません。ブログの内容もきちんと検証して使用してください。英語の勉強のため、英語の

FullText Search

 出張帰りの新幹線でちょっと時間があるので、記事を書きます。昔色々ハマったSQL Server全文検索について書きたいと思います。

 私は、SQL Server を2005で初めて経験し、その時 FullText Search (全文検索)を担当プロジェクトで導入しました。しかし SQL Server 2005 では、検索が遅く、全文検索のインデックスファイルがバックアップスケジュールに組み込めないなど開発・運用含めて色々な問題がありました。

 SQL Server 2008 になり、全文検索インデックスがデータベースファイルに統合され、SQL Server のバックアップに統合可能になったことで、運用面での問題はかなり解消されました。しかし、依然として検索スピードはサーバ負荷のピーク時になると中々レスポンスが出ない...といった状態でした。

 

 ちょっと古い記事ですが、DB Online の日本マイクロソフト)平山さんが書いた記事に SQL Server 2012 の全文検索機能の改善・機能追加項目について詳しく書いてありました。URLは下記の通りです。

記事をさらっと読んでみましたが、SQL Server 2012 になって、かなり改善・機能追加されていますね。個人的に気になった部分を抜き出してみます。

  • 検索処理の並列化
    >> 実は SQL Server 2008 R2 まで、フルテキストインデックスに対する検索は、たった一つのスレッドで実行されていました。そんな状況であれば、当然のことながら巨大なサイズのフルテキストインデックスに対しては、それなりの検索時間が必要となってしまうのは自明ともいえました。そして、ついにSQL Server 2012 からは複数スレッドによって検索処理の並列実行が行わるようになりました。これによって、より大きなフルテキストインデックスに対する検索スピードを短縮することでき、スケーラビリティの向上につながります。
    →MAX DOP指定で並列化できるんですかね?
  • マスターマージ処理の並列化
    >> SQL Server 2008 R2 までは、マスターマージ処理がひとつのスレッドだけを使用して行われていました。想像に難くないと思いますが、サイズの非常に大きなテーブルではとても長い時間が必要でした。数日から1週間といった期間が必要となってしまうような場合さえありました。SQL Server 2012 からは、マスターマージ処理が複数スレッドをつかった並列処理で行われることから、運用作業の負荷を大幅に軽減することができます。
    →ああ、これ。1週間以上かかった経験あります。お客さんに検索にヒットしないとか怒られた記憶があります。複数で行った場合、リソース不足で結局IO過多になったりしないかな?
  • フィルタテーブルのブロッキング解消
    >> SQL Server 2008 R2 までのフルテキストインデックスでは、内部的に使用されるフィルタテーブルをもっていました。そのテーブルにはフルテキストインデックス内のデータと、元テーブルの該当するデータの状況を示す情報が格納されています。元テーブルのデータがすでに更新されている場合などに、一致するフルテキストインデックスのデータが最新ではないことを示すためのデータを保持しています。そのためフルテキストインデックスに対してクエリを実行すると、データの状態を確認するためにフィルタテーブルが参照され、その期間は共有ロックが獲得されます。また、元データの更新がおこわなれるとフィルタテーブルへの排他ロックが獲得されます。負荷の高いシステムでは、それぞれの処理が干渉しあってブロッキングが発生し、スループットを低下させる大きな要因となっていました。SQL Server 2012では、ブロッキングを発生されるフィルタテーブルの使用を廃止しました。その代りにデータのバージョニングによる管理を新たに導入し、参照クエリの実行を妨げることなくロック競合の防止を実現しています。
    →サーバの負荷が高く、検索・更新処理が多数発生するときに、極端に検索が遅くなるのは、これが主原因だったんですね。
  • メモリリソースの効率的な使用
    >> 1.NUMA (Non-Uniform Memory Access)アーキテクチャへの対応
    2.フルテキストインデックスのフラグメント作成時のメモリ使用量の見直し/削減
    →FullTextのデーモンがNUMAに対応されてなかったんですね。複数SOCKETで思うようにレスポンスが出なかったのもこれのせいですかね?

SQL Server 2012 の全文検索は期待できます!!

※なんとか、1時間ちょっとで調査および記事を書き上げることができました。