3

テーブルにテキスト データ型のフィールドがあります。

次の 2 つの SQL クエリのパフォーマンスに違いはありますか。

 select * from tablename where fieldname="xyz%";
 select * from tablename where fieldname="%zyx";

これらのクエリの実行を実装する場合、これが必要になると思います。

2 つの正規表現 (xyz* と *zyx) を一致させる必要があります。

文字列 chars を最初から 1 つずつチェックする必要があります。

最初のクエリでは、一致するかどうかを確認するために最初の 3 文字を読み取る必要がありますが、2 番目のクエリでは、一致が発生したかどうかを判断するために、文字列の末尾を取得するまで読み取る必要があります。しかし、文字列の長さがどこかに格納されている場合、最後の 3 文字を直接読み取ることができ、最初のケースと同様のパフォーマンスが得られます。

私の質問は、mysql や oracle などの商用データベースで、クエリの実行のパフォーマンスに違いがあるかどうかです。

4

4 に答える 4

6

すべての DB のパフォーマンスには明確な違いがあります。列にインデックスが付けられている場合、最初のケースは間違いなく高速になります。

私のプロジェクトには、ユーザーが「で終わる」(2番目のクエリのように) を検索することも許可されている同様のインスタンスがありました。

これは頻繁に使用される操作であり、クエリが遅かったため、

  1. フィールド名の逆順を格納する列をテーブルに追加しました。
  2. この列に索引を付けました
  3. was Search で終わるたびに、この新しい列で検索しました :) (元の検索文字列を逆にして)

したがって、2番目のクエリは次のようになります。

 select * from tablename where fieldname_rev="xyz%";

このアプローチにより、クエリで開始するのと同じくらい速くなりました。

于 2010-08-15T07:36:21.127 に答える
4

あなたのコメントからピックアップ:「一致で始まるものと一致で終わるものが異なるかどうかを知りたいだけです」。

まず、文字列に一致する最適なアルゴリズムを探しているわけではないことを思い出してください。N行のセットで一致するすべての文字列を見つけるための最良のアルゴリズムを探しています。「アルゴリズムを X、N 回実行する」よりもうまくやりたいのです。

fieldname がインデックス化されていない場合、2 つのクエリのパフォーマンスにほとんど違いはありません。SQL エンジンは、文字列の最初の 3 バイトまたは最後の 3 バイトで一致を実行するだけです。これは単にオフセットの問題です。正しい記憶場所。

フィールド名がインデックス化されている場合、N 行すべてを調べるのではなく、ほとんどのデータを破棄できるため、2 つの検索のパフォーマンスに大きな違いがあります。

つまり、「xyz%」バージョンの場合、バイナリ検索を使用できます。

たまたま「ピーター」である中央の要素から始めます。'peter' の前のすべてをすぐに破棄し、'xyz' で始まるエントリが見つかるまで、残りの中間要素 ('samantha' など) を取得できます。

「%xyz」バージョンでは、すべての文字列が最後に一致する可能性があるため、これを行うことはできません。すべての文字列を確認する必要があります。

テーブルのサイズが拡大するにつれて、これら 2 つのアプローチの違いは大きくなります。

フィールド名の逆のフィールド/インデックスを作成するソリューションにより、バイナリ検索手法を再度使用できます。(一部のデータベースでは、追加のフィールドを作成せずに、特定のインデックス タイプや仮想列などを使用することで、実際にこれを行うことができます)。

これはかなり単純化されています。データベース インデックスの実際の実装の詳細については、B-Tree および B*Tree インデックスを参照してください。

于 2010-08-15T13:45:59.900 に答える
2

がインデックス化されている場合fieldname、ほとんどの商用データベースは最初のクエリを間隔検索に変換できます

select * from tablename where fieldname>="xyz" and fieldname<"xy{"

これは非常に高速です。

于 2010-08-15T06:40:07.893 に答える
1

はい、次の 2 つのクエリには違いがあります。

select * from tablename where fieldname LIKE "xyz%";
select * from tablename where fieldname LIKE "%zyx";
  1. 等号 ("=") 演算子は、SQL でワイルドカードを使用できません。使用する必要があります。LIKE
  2. クエリが全然違う
    • 「xyz%」は「xyz」で始まるレコードを返します
    • 「%xyz」は、「xyz」で終わるレコードを返します
  3. 列にインデックスが存在すると仮定するとfieldname、「%xyz」はインデックスを使用できませんが、「xyz%」は使用できます。つまり、より高速になります。

テキスト内の部分文字列を見つける最速の方法は、全文検索 (FTS) を使用することです。Oracle と MySQL の両方に独自のネイティブ機能があり、Sphinx や Solr などのサードパーティ ツールがあります。

于 2010-08-15T21:41:43.550 に答える