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


22

LIKE演算子が現在のデータベースシステム(MySQLやPostgresなど)にどのように実装されているかを説明できますか?またはそれを説明するいくつかの参照を教えてください?

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

回答:


19

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

SELECT *
  FROM employees
 WHERE last_name LIKE 'Cav%'

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

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

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

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


4
オラクルは、先頭のパーセントでもインデックスを使用できます。検索されるデータが行の小さなサブセットを表す場合、ヒントはインデックスを使用するように強制し、実行を高速化できます。laurentschneider.com/wordpress/2009/07/…を参照してください。
リーリッフェル

1
「テーブル全体をスキャンします...明らかに、それは非常に高価です」-それはむしろテーブルに依存します;)ps LAST_NAMEクラスター化インデックス(の最初の列)の候補になることに同意しますか?データベースシステムがディスク上の連続ストレージとBツリーインデックスに基づいていると、この答えはどの程度ppsですか?
いつか

26

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

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は彼のブログに新機能に関する素晴らしい記事を書いています。

GINまたはGiST?

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

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

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

これは、GINインデックスではなく、GiSTインデックスによって非常に効率的に実装できます。


3
これを読んで、GINを使用するかGiSTを使用するかを考えました。私が読んだことによると、GINインデックスは維持費は高くなりますが検索は速くなりますが、GiSTインデックスは維持費は安くなりますが検索は遅くなります。つまり、GINインデックスは一般に比較的静的なデータで使用する必要がありますが、GiSTインデックスはより頻繁に変化するテーブルで優先されます。
コリン

1
@ Colin'tHart:それは一般的に真実ですが、ルールには例外があります。上記の補遺を検討してください。
アーウィンブランドステッター

5

MySQLについて言えば、ワイルドカード文字(%)の位置に違いがあります。テキストの最初の部分を同様に指定されている場合はwhere first_name like 'Sta%'、その後、DBエンジンは、セントに行く、Sで見つめて言葉だけより小さなサブセットを検索します、その後、駅、など、あなたのような何かを行う場合はwhere first_name like '%stan%'、その後の全体のスキャンを、列が必要になります。また、自然言語検索も行うフルテキストインデックスを調べることもできます。こちらのMySQLドキュメントをご覧ください。


1
部分文字列が3文字に定義されているときに「S%」の検索を開始するのはなぜですか(つまり、文字列が「Sr%」ではないことがわかっています)。または、DBが属性の上にプレフィックスツリーを持ち、このツリーを走査する例を提供すると仮定しましたか?
ニック
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.