web-dev-qa-db-ja.com

innoDBでのMySQLLIKE '%string%'クエリの最適化

このテーブルを持っている:

CREATE TABLE `example` (
`id` int(11) unsigned NOT NULL auto_increment,
`keywords` varchar(200) NOT NULL,
PRIMARY KEY  (`id`)
) ENGINE=InnoDB;

次のクエリを最適化します。

SELECT id FROM example WHERE keywords LIKE '%whatever%'

テーブルはInnoDBです(したがって、今のところFULLTEXTはありません)。これは、このようなクエリを最適化するために使用するのに最適なインデックスですか?

簡単なことを試しました:

ALTER TABLE `example` ADD INDEX `idxSearch` (`keywords`);

しかし、explainクエリは、テーブル全体をスキャンする必要があることを示しています。代わりにLIKE'whatever% 'のクエリを実行すると、このインデックスは正常に機能しますが、それ以外の場合は値がありません。

これをinnoDB用に最適化する方法はありますか?

ありがとう!

19
jmserra

インデックスは、文字列の最初から最後に向かって作成されます。 LIKE 'whatever%' type句を使用すると、MySQLはこれらの開始ベースのインデックスを使用してwhateverを非常に迅速に検索できます。

ただし、LIKE '%whatever%'に切り替えると、文字列の先頭にあるアンカーが削除されます。検索語が文字列の先頭に固定されなくなったため、開始ベースのインデックスを使用できなくなりました。文字列は中央のどこかに「フローティング」されており、フィールド全体を検索する必要があります。 LIKE '%...クエリはインデックスを使用できません。

そのため、フルテキストインデックスは、そのタイプの使用法向けに設計されているため、「フローティング」検索のみを実行している場合に使用します。

重要な注意事項:InnoDBは現在 フルテキストをサポート バージョン5.6.4以降のインデックス。したがって、少なくとも5.6.4にアップグレードできない場合を除いて、InnoDB *[〜#〜]および[〜#〜]の使用を妨げるものは何もありません。 -)全文検索。

45
Marc B

驚くべきことに、インデックスを作成することで、私の場合はlike '%abc%'クエリのクエリを高速化することもできたとコメントしたいと思います。

UbuntuMySQL 5.5.50を実行して(すべてをデフォルトのままにします)、多くの列を含むテーブルを作成し、100,000ダミーエントリを挿入しました。 1つの列に、32文字の完全にランダムな文字列を挿入しました(つまり、すべて一意です)。

いくつかのクエリを実行してから、この列にインデックスを追加しました。シンプルな

select id, searchcolumn from table_x where searchcolumn like '%ABC%'

~2 secondsなしインデックスと0.05 secondsありインデックスで結果を返します。

これは上記の説明(および他の多くの投稿)に適合しません。その理由は何でしょうか?

[〜#〜] edit [〜#〜] EXPLAINの出力を確認しました。出力には、行は100,000と表示されますが、追加情報は「Using where; Using index」です。では、どういうわけか、DBMSはすべての行を検索する必要がありますが、それでもインデックスを利用できますか?

0
abulhol