web-dev-qa-db-ja.com

SQLで部分文字列から文字列を見つける最も速い方法は?

IdとTitleの2つの列を持つ巨大なテーブルがあります。 Idはbigintであり、タイトル列のタイプ(varchar、char、textなど)を自由に選択できます。列タイトルには、「abcdefg」、「q」、「allyourbasebelongtous」などの最大255文字のランダムなテキスト文字列が含まれます。

私の仕事は、与えられた部分文字列で文字列を取得することです。サブストリングもランダムな長さで、ストリングの開始、中間、または終了にすることができます。それを実行する最も明白な方法:

SELECT * FROM t LIKE '%abc%'

INSERTは気にしません。必要なのは高速選択だけです。検索をできるだけ速く実行するにはどうすればよいですか?

私はMS SQL Server 2008 R2を使用していますが、私の知る限り、全文検索は役に立ちません。

22
msergey

ランディの答えよりも少ないスペースを使用したい場合で、データにかなりの繰り返しがある場合は、各Edgeが次の文字であるN-Aryツリーデータ構造を作成し、データの各文字列と後続のサブ文字列を掛けることができます。

ノードには、最初に深さ順に番号を付けます。次に、レコードごとに最大255行のテーブルを作成できます。レコードのIDと、文字列または末尾の部分文字列と一致するツリー内のノードIDを使用できます。次に、検索を実行すると、検索している文字列(およびすべての後続の部分文字列)を表すノードIDが見つかり、範囲検索が実行されます。

7
antlersoft

ストレージに関心がない場合は、部分文字列で始まる部分的なTitleエントリを持つ別のテーブルを作成できます(通常のtitleあたり最大255エントリ)。

このようにして、これらの部分文字列にインデックスを付け、文字列の先頭にのみ一致させると、パフォーマンスが大幅に向上します。

13
Randy

あなたはすべての良い選択肢を除外しているように聞こえます。

あなたはすでにあなたのクエリを知っています

SELECT * FROM t WHERE TITLE LIKE '%abc%'

インデックスを使用せず、毎回全テーブルスキャンを実行します。

文字列がフィールドのbeginningにあることが確実な場合は、

SELECT * FROM t WHERE TITLE LIKE 'abc%'

titleのインデックスを使用します。

ここで全文検索が役に立たないと確信していますか?

ビジネス要件に応じて、次のロジックを使用することがあります。

  • 「で始まる」クエリ(LIKE 'abc%')最初に、インデックスを使用します。
  • 行が返されるかどうか(または行の数)に応じて、フルスキャンを実行する「ハード」検索(LIKE '%abc%'

もちろん、必要なものによって異なりますが、私はこれを最も簡単で最も一般的な結果を最初に示し、必要な場合にのみより難しいクエリに進むことができる状況で使用しました。

4
BradC

テーブルに別の計算列を追加できます:titleLength as len(title)PERSISTED。これは「タイトル」列の長さを格納します。これにインデックスを作成します。

また、ReverseTitle as Reverse(title)PERSISTEDと呼ばれる別の計算列を追加します。

ここで、誰かがキーワードを検索するときに、キーワードの長さがtitlelengthと同じかどうかを確認します。その場合は、「=」で検索してください。キーワードの長さがtitleLengthの長さより短い場合は、LIKEを実行します。ただし、最初にタイトルをLIKE 'abc%'にしてから、reverseTitle LIKE 'cba%'を行います。ブラッドのアプローチに似ています。つまり、必要な場合にのみ次の難しいクエリを実行します。

また、80〜20のルールがキーワード/サブストリングに適用される場合(つまり、ほとんどの検索が少数のキーワードで行われる場合)、何らかのキャッシュの実行を検討することもできます。たとえば、「abc」というキーワードで多くのユーザーが検索し、このキーワード検索でIDが20、22、24、25のレコードが返されたとします。これを別のテーブルに保存し、インデックスを付けることができます。そして、誰かが新しいキーワードを検索するとき、最初にこの「キャッシュ」テーブルを見て、検索が以前のユーザーによって既に実行されたかどうかを確認します。その場合は、メインテーブルをもう一度確認する必要はありません。 「キャッシュ」テーブルから結果を返すだけです。

上記をSQL Server TextSearchと組み合わせることもできます。 (あなたがそれを使用しない正当な理由があると仮定します)。ただし、それでも最初にテキスト検索を使用して結果セットを候補から除外することができます。次に、テーブルに対してSQLクエリを実行し、TExt検索によって返されたIDをキーワードと一緒にパラメーターとして使用して、正確な結果を取得します。

これは明らかに、SQLを使用する必要があることを前提としています。そうでない場合は、Apache Solrのようなものを探索できます。

インデックスビューを作成するsql create indexの列に新しい機能があり、検索後にそのビューを使用して、より高速な結果を得ることができます。

0
KuldipMCA

1つのことを行い、特定の列で主キーを使用し、それをクラスター形式でインデックス付けします。

次に、任意の方法(ワイルドカードまたは=またはany)を使用して検索します。テーブルがすでにクラスター化された形式であるため、最適に検索され、検索できる場所がわかります(列が既に並べ替えられているため)。

0
Mohit Verma
  1. [〜#〜] ascii [〜#〜] charsetをclustered indexing char列で使用します。 RAMとディスクの両方のデータサイズのため、文字セットは検索パフォーマンスに影響します。多くの場合、ボトルネックはI/Oです。
  2. 列の長さが255文字であるため、フルテキストではなく、charフィールドで通常のインデックスを使用できます。 selectステートメントで不要な列を選択しないでください。
  3. 最後に、さらにRAM=サーバーに追加して、キャッシュサイズを増やします。
0