web-dev-qa-db-ja.com

全文検索とLIKEとは

SQLの「全文検索」に関する記事を読んだところです。

FTSとLIKEの違いは何なのかと思っていました。私はいくつかの記事を読みましたが、それをうまく説明するものを見つけることができませんでした。

120
Nathan W

一般に、「精度」と「リコール」の間にはトレードオフがあります。高精度とは、関連性の低い結果が少なく表示されること(誤検出なし)を意味し、再現率が高いと、関連する結果が欠落する数が少なくなります(誤検出なし)。 LIKE演算子を使用すると、100%の精度が得られ、リコールの許可もありません。全文検索機能を使用すると、リコールの精度を下げるための柔軟性が大幅に向上します。

ほとんどの全文検索の実装では、「逆索引」が使用されます。これはキーが個々の用語であるインデックスであり、関連する値はその用語を含むレコードのセットです。全文検索は、これらのレコードセットの共通部分、結合などを計算するために最適化され、通常、特定のレコードが検索キーワードにどれだけ強く一致するかを定量化するランキングアルゴリズムを提供します。

SQL LIKE演算子は非常に効率が悪い場合があります。インデックスなしの列に適用すると、完全なスキャンを使用して一致が検出されます(インデックスなしのフィールドでのクエリと同様)。列にインデックスが付けられている場合、インデックスキーに対して照合を実行できますが、ほとんどのインデックス検索よりもはるかに効率が低下します。最悪の場合、LIKEパターンには、すべてのインデックスキーの調査を必要とする主要なワイルドカードが含まれます。対照的に、多くの情報検索システムでは、選択したフィールドでサフィックスツリーをプリコンパイルすることにより、主要なワイルドカードをサポートできます。

全文検索の典型的なその他の機能は次のとおりです。

  • 字句解析またはトークン化-非構造化テキストのブロックを個々の単語、フレーズ、および特別なトークンに分割
  • 形態素解析、またはステミング-特定の単語のバリエーションを1つのインデックス用語に折りたたみます。たとえば、「マウス」と「マウス」、または「電化」と「電気」を同じ言葉として扱う
  • ランキング-一致するレコードとクエリ文字列の類似性を測定する
146
erickson

FTSでは、多くのレコードをすばやく検索できるように、テキストフィールド内の個々の単語にインデックスを付けます。 LIKEを使用するには、フィールド内で文字列検索(線形など)を実行する必要があります。

MySQLは、有効な全文検索列の単語からインデックスを作成し、このインデックスで検索を実行します。 MySQLは高度なアルゴリズムを使用して、検索クエリと一致する行を決定します。

また、 this SO answer

全文検索にはいくつかの利点があります。

インデックス:

何かのようなもの:

WHERE Foo LIKE '%Bar';

インデックスを利用できません。すべての行を調べて、一致するかどうかを確認する必要があります。ただし、フルテキストインデックスは可能です。実際、フルテキストインデックスを使用すると、一致する単語の順序、それらの単語がどれだけ近いかなどの点で柔軟性が大幅に向上します。

ステミング:

全文検索は単語をステミングできます。 runを検索すると、「ran」または「running」の結果を取得できます。ほとんどのフルテキストエンジンには、さまざまな言語のステム辞書があります。

加重結果:

フルテキストインデックスには、複数の列を含めることができます。たとえば、「Peach pie」を検索でき、インデックスにはタイトル、キーワード、本文を含めることができます。タイトルに一致する結果は、より関連性が高く、より高い重みを付けることができ、ソートして上部近くに表示できます。

デメリット:

フルテキストインデックスは、標準のB-TREEインデックスよりも何倍も大きくなる可能性があります。このため、データベースインスタンスを提供する多くのホストプロバイダーは、この機能を無効にするか、少なくとも追加料金を請求します。たとえば、最後に確認したように、Windows Azureはフルテキストクエリをサポートしていませんでした。

フルテキストインデックスの更新も遅くなる可能性があります。データが大きく変化する場合、標準のインデックスと比較して、インデックスの更新に多少の遅れが生じる可能性があります。

17
Vipin Jain

同様に、ワイルドカードのみを使用し、それほど強力ではありません。

フルテキストを使用すると、And、Or、Not、同様のサウンディング結果(SOUNDEX)など、はるかに複雑な検索が可能になります。

SQL CONTAINS()FREETEXT()および関連する全文検索項目を調べて、利用可能なものをよりよく理解できるようにします。

15
Mitchel Sellers

本当の違いは、スキャン方法です。全文検索では、単語(用語)がハッシュキーとして使用されます。各単語は、キー(用語)が表示されるドキュメントの配列に関連付けられています。次のようになります。

Document sets = {d1, d2, d3, d4, ... dn}
Term sets = {t1, t2, t3, .. tn}

ここで、用語文書マトリックス(どの文書のどの用語メンバー)は、次のように表すことができます。

t1 -> {d1, d5, d9,.. dn}
t2 -> {d11, d50, d2,.. dn}
t3 -> {d23, d67, d34,.. dn}
:
tn -> {d90, d87, d57,.. dn}

「Word/term t1を含むすべてのドキュメントを取得してください」という要求が来たら、ドキュメントセット{d1, d5, d9,.. dn}が返されます。

非正規化テーブルスキーマをハックしてドキュメントを保存できます。MySQLテーブルの各行は「ドキュメント」と見なされ、TEXT列には段落などが含まれます。逆索引には、ハッシュキーおよび行IDとして用語が含まれますドキュメントIDとして。

このSQLクエリのパフォーマンスは多かれ少なかれO(1)パフォーマンスです。クエリは独立しています

  1. TEXT列の単語/用語の数
  2. 基準に一致する行/文書の数
  3. 単語/用語の長さ

たとえば、このSQLを起動して、指定されたWord XYZに一致するすべての行を抽出できます。

SELECT * 
FROM   my_table 
WHERE  MATCH (my_text_column) against ('XYZ' IN boolean mode) ;

警告:このクエリにORDER BYを追加すると、ランタイムはいくつかのパラメーターによって異なります。パラメーターの1つは、一致する行/ドキュメントの数です。だから注意してください。

しかし、LIKEはこれを何も持っていません。文/文字列を直線的にスキャンし、一致するすべての用語を見つける必要があります。ワイルドカードを追加すると混乱が増します。ご想像のとおり、短い文字列に対してはうまく機能しますが、長い文に対しては惨めに失敗します。また、段落やページ全体のテキストなどがある場合、間違いなく比較できません。

10
Kingz

FTSはより効率的で強力です(特にワードブレーカーと語幹機能について)...しかし、DBはすべての言語をサポートしていない場合があるため、要件を確認してください。たとえば、MSSQLはギリシャ語をサポートしていません(このページで確認してください http: //msdn.Microsoft.com/en-us/library/ms176076(v=sql.110).aspx

3
kamskyleo