web-dev-qa-db-ja.com

LIKEはどのように実装されていますか?

LIKE演算子が現在のデータベースシステム(MySQLやPostgresなど)にどのように実装されているかを誰かが説明できますか?それともそれを説明するいくつかの参照を私に指摘しますか?

素朴なアプローチは、各レコードを検査し、対象のフィールドで正規表現または部分的な文字列の一致を実行することですが、これらのシステムはよりスマートなことをしていると感じています(期待しています)。

23
Nick

いいえ、それは彼らがやっていることのほとんどです。現在、先行するワイルドカードがなく、フィールドにインデックスが付けられている場合(これが通常の状況です)、データベースエンジンは正規表現をインデックスに適用できます。したがって、たとえば、

SELECT *
  FROM employees
 WHERE last_name LIKE 'Cav%'

データベースはLAST_NAMEのインデックスを使用して、姓が「Cav」で始まるすべての行を検索できます。一方、次のようなものがある場合

SELECT *
  FROM employees
 WHERE last_name LIKE '%av%'

データベースはテーブル全体(またはインデックス全体)をスキャンし、完全なLAST_NAME値に対して式を評価する必要があります。明らかに、それは非常に高価です。

優れたリレーショナルデータベースのほとんどは、さまざまな種類のインデックスとテキストカタログを作成することにより、より効率的な方法でフルテキスト検索を実行する機能を備えていますが、これらはLIKEキーワードを使用しません。たとえば、これは PostgreSQLでの全文検索 について説明する素晴らしい記事です。

19
Justin Cave

PostgreSQL 9.1以降、Justin Caveが書いたものに加えて、LIKEany検索を高速化できます~~)またはILIKE~~*)、および基本的な正規表現も一致します(~)。モジュールが提供する演算子クラス pg_trgm をGINまたはGistインデックスとともに使用して、残されていないLIKE式を高速化します-アンカー。拡張機能をインストールするには、データベースごとに1回実行します。

CREATE EXTENSION pg_trgm;

フォームのインデックスを作成する

CREATE INDEX tbl_col_gin_trgm_idx ON tbl USING gin (col gin_trgm_ops);

または:

CREATE INDEX tbl_col_Gist_trgm_idx ON tbl USING Gist (col Gist_trgm_ops);

GINまたはGistインデックス の作成と維持にはコストがかかりますが、テーブルがあまり書かれていない場合、これは素晴らしいことですあなたのための機能。

Depesz が彼のブログに新機能について excellent article を書いています。

GINまたはGiST?

これら2つの マニュアルからの引用 はいくつかのガイダンスを提供するはずです

GistインデックスとGINインデックスのどちらを選択するかは、他の場所で説明するGistとGINの相対的なパフォーマンス特性によって異なります。経験則として、GINインデックスはGistインデックスよりも検索が高速ですが、構築や更新は低速です。したがって、GINは静的データに、Gistは頻繁に更新されるデータに適しています。

ただし、距離演算子<->を使用した「最も近い」タイプのクエリの場合:

これはGistインデックスではかなり効率的に実装できますが、GINインデックスでは実装できません。

28

MySQLについて言えば、ワイルドカード文字(%)の位置が違います。テキストの最初の部分がwhere first_name like 'Sta%'のように指定されている場合、DBエンジンはSで始まる単語の小さなサブセットのみを検索し、次にSt、次にStaなどに移動します。where first_name like '%stan%'の場合、列全体のスキャンが必要になります。自然言語検索も行うフルテキストインデックスを調べることもできます。 MySQLのドキュメントはこちらで確認してください。

5
StanleyJohns