2016-11-09 4 views
1

このSQLコードを使用すると、列に適切なインデックスが適用されていると思われます。ORを使用したMySQL ilikeのパフォーマンスは%%より優れていますか?

定数はテキストフィールドからの入力ですとしましょう!

select ... 
from ..... 
where lower(column) like 'Constant%' or lower(column) like '%Constant%' 

より優れていますか?私のような使用が、私は完全な一致をしようと試合以降を見つけることが幸運であることしようとしたインデックスを使用して「定数」を一致させようと最初のコードで

select ... 
from ..... 
where lower(column) like '%Constant%' 

!!

私が望むのは、私のパフォーマンスが低下していないことです!両方のクエリは、クエリが時々パフォーマンスのアップグレードを取得することができ、同じ時間にまたは場合に実行すると、私と一緒に

OKであれば、私たちはDEFAULT CHARSET = UTF8のCOLLATE = utf8_bin

答えて

2

私は少しのテーブルを作成しました:

create table dotdotdot (
    col varchar(20), 
    othercol int, 
    key(col) 
); 

私はあなたが示したものと類似したクエリにEXPLAINでした:それは、インデックスを使用することはできません

explain select * from dotdotdot where lower(col) = 'value'\G 
*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: dotdotdot 
    partitions: NULL 
     type: ALL 
possible_keys: NULL 
      key: NULL 
     key_len: NULL 
      ref: NULL 
     rows: 1 
    filtered: 100.00 
     Extra: Using where 

お知らせtype: ALLcolにあります。 lower()関数を使用すると、MySQLがインデックスを使用する能力が損なわれ、すべての行の式を評価するテーブルスキャンに頼らざるを得なくなります。あなたのテーブルが大きくなるにつれ、これはますます高価になります。

とにかくそれは不要です!文字列の比較は、デフォルトの照合では大文字と小文字を区別しません。したがって、大文字と小文字を区別する照合またはバイナリ照合を使用してテーブルを意図的に宣言しない限り、lower()関数呼び出しをスキップするだけでよいので、インデックスを使用できます。

例:

explain select * from dotdotdot where col = 'value'\G 
*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: dotdotdot 
    partitions: NULL 
     type: ref 
possible_keys: col 
      key: col 
     key_len: 23 
      ref: const 
     rows: 1 
    filtered: 100.00 
     Extra: NULL 
type: ref

非一意のインデックスの使用を示しています。

また、パターンマッチングにワイルドカードを使用する方法と比較してください。これはまた、インデックスの使用を無効にし、テーブルスキャンを実行する必要があります。

パターンマッチングにこのようなワイルドカードを使用すると、非常に効率が悪いです。

代わりにフルテキストインデックスを使用する必要があります。 ORを使用する場合に役立ちますあなたが求める他の回答ではhttps://www.youtube.com/watch?v=-Sa7TvXnQwY


は、あなたは私のプレゼンテーションFull Text Search Throwdown、ここでビデオを好きかもしれません。 それはしません。

explain select * from dotdotdot where col like 'value%' or col like '%value%'\G 
*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: dotdotdot 
    partitions: NULL 
     type: ALL 
possible_keys: col 
      key: NULL 
     key_len: NULL 
      ref: NULL 
     rows: 1 
    filtered: 100.00 
     Extra: Using where 

お知らせオプティマイザは可能キーとしてCOLインデックスを識別するが、その後最終的に(key: NULL)を使用しないことを決定します。

1

いいえ、これを使用するので、私は下の使用を意味しますクエリのパフォーマンスが大幅に向上することはありません。 MySQLはWHERE句を「行ごとに」一致させるため、次の行に進む前にすべての条件を検査します。インデックスが最初に当てはまると、パフォーマンスがわずかに向上する可能性がありますが、最初の条件が一致しない場合はダブル評価によってこのゲインが引き継がれる可能性が最も高いです。役立っている可能性が何

は次のとおりです。

1)like 'Constant%'

2でクエリを実行する)がある場合、最初の1が加速することができる。その場合、中like '%Constant%'

で別のクエリを実行します。一致。 しかし、オーバーヘッドに悩まされ、2つのクエリで1つより悪く実行されます。

さらに、LIKE演算子は大文字と小文字を区別しません。したがって、lower(column)は不要です。

一方、データが主に最初の条件で一致することを期待し、2番目の条件にほとんど一致しない場合は、2番目の条件が評価されないために増加します。

+0

次の行に進む前にすべての条件を検査します。あなたは何を意味するのですか?ORはSQLの短絡です。もし最初のようなものが次のものが無視されるならば? – chiperortiz

+0

一致がある場合はyesですが、そうでない場合は一致しません。評価する条件が増えたために得られる利益は失われます。私は私の答えを詳述しました。 – Simon

+0

ありがとう、私の欲しいのは私のパフォーマンスが低下していないことです!クエリが時々パフォーマンスのアップグレードを得ることができる場合は私と一緒にOKです。 – chiperortiz

1

LOWER()を使用すると、インデックスを使用できなくなります。したがって..._ci照合に切り替えてLOWERを削除してください。

FULLTEXTインデックスを考えてみましょう。それはより速くLIKE%... `です。前者は高速です。後者はフルテーブルスキャンです。

ORは、ほとんど常にパフォーマンスのキラーです。

関連する問題