MySQL列(タイプ 'varchar'、 'text'、 'blob'など)に文字列が存在するかどうかをテストすることが目的である場合、次のうちどれがより高速で/より効率的/より使いやすく、なぜですか?
または、これらのいずれかを上回る他の方法はありますか?
INSTR( columnname, 'mystring' ) > 0
対
columnname LIKE '%mystring%'
上記のコメントでkibibuが指摘したように、FULLTEXT検索は絶対的に高速になります。
ただし:
mysql> select COUNT(ID) FROM table WHERE INSTR(Name,'search') > 0;
+-----------+
| COUNT(ID) |
+-----------+
| 40735 |
+-----------+
1 row in set (5.54 sec)
mysql> select COUNT(ID) FROM table WHERE Name LIKE '%search%';
+-----------+
| COUNT(ID) |
+-----------+
| 40735 |
+-----------+
1 row in set (5.54 sec)
私のテストでは、まったく同じように動作します。どちらも大文字と小文字を区別せず、通常、フルテーブルスキャンを実行します。これは、高性能のMySQLを処理する場合は一般的にノーノーです。
インデックス付きの列でプレフィックス検索を実行している場合を除きます。
mysql> select COUNT(ID) FROM table WHERE Name LIKE 'search%';
+-----------+
| COUNT(ID) |
+-----------+
| 7 |
+-----------+
1 row in set (3.88 sec)
その場合、サフィックスワイルドカードのみを使用したLIKEの方がはるかに高速です。
MySQL-[〜#〜] instr [〜#〜] vs [〜#〜] locate [〜#〜] vs [〜#〜] like [〜#〜] vs [〜#〜] regexp [〜#〜]
私にとって[〜#〜] instr [〜#〜]および[〜#〜] locate [〜#〜]は最も高速に実行されました:
# 5.074 sec
SELECT BENCHMARK(100000000,INSTR('foobar','foo'));
# 5.086 sec
SELECT BENCHMARK(100000000,LOCATE('foo','foobar'));
# 8.990 sec
SELECT BENCHMARK(100000000,'foobar' LIKE '%foo%');
# 14.433 sec
SELECT BENCHMARK(100000000,'foobar' REGEXP 'foo');
# 5.5.35-0ubuntu0.12.10.2
SELECT @@version;
ここにあるように思われる「フロントワイルドカード」(つまり、「LIKE '%...'」述語)の場合、INSTRとLIKEはほぼ同じように動作するはずです。
ワイルドカードが「フロントワイルドカード」ではない場合、ワイルドカードがあまり選択的でない限り、LIKEアプローチはより高速になります。
理由ワイルドカードの種類とその選択性が重要な理由は、INSTR()を含む述語が体系的に結果としてテーブルになるためですスキャン(SQLはINSTRのセマンティクスについて想定できない)。これにより、SQLはLIKE述語のセマンティクスの理解を活用して、インデックスを使用して、一致する可能性のあるセットのテストのみを支援することができます。
質問自体の下のコメントで示唆されているように、フルテキストインデックスははるかに高速になります。違いは、テキスト内の単語の特定の分布、および全体的なテーブルサイズなどにも依存しますが、2倍から10倍程度の速度が期待されます。
フルテキストインデックスで使用する場合の考えられる欠点は、そのようなインデックスを作成するための一般的なオーバーヘッドに加えて、このインデックスの構成に細心の注意を払わない限り(たとえば、ストップワードリストの定義、特定の検索構文を使用して屈折形を回避し、同様...)、FullTextによって提供される結果が期待どおりにならない場合があります。たとえば、「SAW」(木を切るためのツール)を検索すると、さまざまな活用形の「to see」という動詞を含むレコードが多数ヒットします。
もちろん、フルテキストインデックスのこれらの言語認識機能は通常、オーバーライドできます。また、そのような機能は、欠点ではなく、事実上利点であると考えることもできます。これを単純なワイルドカード検索と比較しているので、ここで触れておきます。
Razzedのテストに追加することはほとんどありません。しかし、明らかにregexp
を使用すると、Sethがコメントで指摘しているものとは異なり、処理負荷が大きくなります 。
次のテストでは、query_caching
からmy.iniのOn
query_cache_type = 1
query_cache_size = 64M
テスト
タイミングは、3つの測定値のうち(キャッシュが断続的にクリアされた状態)の平均パフォーマンスを示しています。
[〜#〜] like [〜#〜]
SELECT * FROM `domain_model_offers` WHERE `description` LIKE '%inform%' LIMIT 0 , 30
初期:0.0035秒
キャッシュ:0.0005秒
[〜#〜] regexp [〜#〜]
SELECT * FROM `domain_model_offers` WHERE `description` REGEXP 'inform' LIMIT 0 , 30
初期:0.01秒
キャッシュ:0.0004s
結果
LIKE
またはINSTR
はREGEXP
よりも明らかに高速です。
キャッシュタイミングの違いは最小限ではありますが、さらなる調査を行うにはおそらく十分です。
おそらく設定されたMySQLシステムでは、フルテキストインデックスは常に高速であるか、少なくともインデックスなしの検索と同等です。したがって、断続的なマークアップコードに関係なく、特に長い人間の言語のテキストではインデックスを使用してください。