web-dev-qa-db-ja.com

複数のインデックスを使用した全文検索

複数の列を持つテーブルがあります。たとえば、abcdで、検索可能にする必要があります。問題は、検索する必要があるときに発生しますa, b, cとは別にd(およびその逆)。私の知る限り、すべての列で1つの複合フルテキストインデックスを使用してこれを実現する方法はないため、次のように2つの個別のインデックスを作成します。

CREATE FULLTEXT INDEX idx1 ON content (a, b, c);
CREATE FULLTEXT INDEX idx2 ON content (d);

これで、1番目と2番目の検索が成功しました。どちらの場合も、次のコマンドを使用します。

SELECT * FROM content 
WHERE MATCH(a, b, c) AGAINST ('keyword')
AND MATCH(d) AGAINST ('keyword');

explainはこれを教えてくれます:

+----+-------------+---------+----------+---------------+------+---------+------+------+-------------+
| id | select_type | table   | type     | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+---------+----------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | content | fulltext | idx1,idx2     | idx1 | 0       |      |    1 | Using where |
+----+-------------+---------+----------+---------------+------+---------+------+------+-------------+

すごい!したがって、2つのインデックスを使用していますが、keywordが両方に含まれ、どちらかが必要な行のみを返すため、ANDORに変更して、次のように説明しています。

+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | content | ALL  | NULL          | NULL | NULL    | NULL |  128 | Using where |
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+

何?突然、それは全表スキャンを行っています。なぜこうなった?これを回避する最良の方法は何でしょうか?

3
bobo

残念ながら、これはMySQL Query OptimizerがFULLTEXTインデックスを処理する方法です。 MATCH句がWHEREの唯一の句である場合、インデックスが使用されます。 ANDと組み合わせて使用​​すると、インデックスが見落とされやすくなります。

私は以前にこの動作について書きました Mysql全文検索my.cnf最適化

提案:2つのFULLTEXT検索の結合としてクエリを書き換えます

SELECT * FROM content 
WHERE MATCH(a, b, c) AGAINST ('keyword')
UNION
SELECT * FROM content 
WHERE MATCH(d) AGAINST ('keyword');

GIT IT A TRY !!!

4
RolandoMySQLDBA

何をしたいのか不明確。

keywordおよびa,b,cのどこかにdを含む行を表示する場合は、ANDが適しています。

ただし、keyworda,b,c,dのいずれかに含めたい場合は、thirdインデックスを追加します

FULLTEXT(a,b,c,d)

そしてに変更

MATCH(a,b,c,d) AGAINST('keyword')

詳細については、InnoDBまたはMyISAMのどちらを使用しているかを指定してください。それらは異なる働きをします。

0
Rick James