MySQLのFULLTEXTインデックスでLIKEがMATCH…AGAINSTより4倍以上速いのはなぜですか?


12

私はこれを取得していません。

これらのインデックスを持つテーブルがあります

PRIMARY     post_id
INDEX       topic_id
FULLTEXT    post_text

テーブルには(のみ)346 000行があります。2つのクエリを実行しようとしています。

SELECT post_id 
FROM phpbb_posts 
WHERE topic_id = 144017 
AND post_id != 155352 
AND MATCH(post_text) AGAINST('http://rapidshare.com/files/5494794/photo.rar')

4.05秒かかります

SELECT post_id 
FROM phpbb_posts 
WHERE topic_id=144017 
AND post_id != 155352 
AND post_text LIKE ('%http://rapidshare.com/files/5494794/photo.rar%')

0.027秒かかります。

EXPLAINは、唯一の違いがpossible_keysにあることを示しています(fulltextpost_textが含まれていますが、含まれてLIKEいません)

それは本当に奇妙です。

この背後にあるものは何ですか?バックグラウンドで何が起こっていますか?LIKEインデックスを使用していない場合はどのように高速になり、インデックスを使用している場合はFULLTEXTが非常に遅くなりますか?

アップデート1:

実際には約0.5秒かかりますが、テーブルがロックされた可能性がありますが、プロファイリングをオンにすると、FULLTEXT INITIALIZATIONに0.2秒かかったことが示されます。調子はどう?

1 LIKE秒あたり10倍、フルテキストは2倍でテーブルをクエリできます

UPDATE2:

驚き!

mysql> SELECT post_id FROM phpbb_posts WHERE post_id != 2 AND topic_id = 6 AND MATCH(post_text) AGAINST ('rapidshare.com');
Empty set (0.04 sec)

だから私は尋ねています、これはどのように可能ですか?

さらに、

SELECT count(*) FROM phpbb_posts WHERE MATCH(post_text) AGAINST ('rapidshare.com')

本当に遅いです。全文が壊れている可能性はありますか?

UPDATE3:

なんてこったい?

SELECT forum_id, post_id, topic_id, post_text  FROM phpbb_posts  WHERE MATCH(post_text) AGAINST ('rapidshare.com') LIMIT 0, 30;

0.27秒かかります

SELECT count(*) FROM phpbb_posts  WHERE MATCH(post_text) AGAINST ('rapidshare.com') LIMIT 0, 30;

30秒以上かかります!ここで何が問題になっていますか?


2つの間の応答時間は、複数の実行で一貫していますか?ディスクキャッシュが最初の「低速」テストで必要なすべてのデータをRAMにロードするため、2番目の「高速」クエリがかなり高速になるため、ディスクキャッシュが機能しているのではないかと考えたくなります。
atxdba 2012年

SQL_NO_CACHEでのみクエリをテストします
mgutt 2015

これはかなり古い質問/回答です。あの頃からmysql / mariadbからの進歩はありますか?
Roman Susi

1
注意:このQ&Aのタイミングは、MyISAMについてのみ話していることを意味します。InnoDBへの適用性には疑問があります。
リックジェームズ

@RomanSusi-InnoDBを対象とした新しい質問を開始しますか?
リックジェームズ

回答:


2

問題はFULLTEXTインデックス自体の存在に起因していると思います。

FULLTEXTインデックスを含むクエリがあるたびに、MySQLクエリオプティマイザーはクエリをフルテーブルスキャンに変換する傾向があります。私は何年にもわたってこれを見てきました。また、FULLTEXTインデックスでのこの最も些細な動作についての以前の投稿も書きました

次の2つのことを行う必要がある場合があります。

  1. FULLTEXTインデックスがMySQLクエリオプティマイザーを混乱状態にしないようにクエリをリファクタリングする
  2. リファクタリングされたクエリを適切にサポートする追加のインデックスを追加します

クエリをリファクタリングする

これが元のクエリです

SELECT post_id  
FROM phpbb_posts  
WHERE topic_id = 144017  
AND post_id != 155352  
AND MATCH(post_text) AGAINST('http://rapidshare.com/files/5494794/photo.rar') 

次のようにクエリをリファクタリングする必要があります:

SELECT subqueryA.post_id
FROM
(
    SELECT post_id FROM phpbb_posts
    WHERE topic_id = 144017
    AND post_id != 155352
) subqueryA
INNER JOIN
(
    SELECT post_id FROM phpbb_posts
    WHERE MATCH(post_text) AGAINST('http://rapidshare.com/files/5494794/photo.rar')
) subqueryB
USING (post_id);

新しいインデックスを作成する

をサポートするにはインデックスが必要subqueryAです。にはすでにインデックスがありますtopic_id。次のように交換する必要があります。

ALTER TABLE phpbb_posts ADD INDEX topic_post_ndx (topic_id,post_id);
ALTER TABLE phpbb_posts DROP INDEX topic_id;

試してみる !!!

UPDATE 2012-03-19 13:08 EDT

まずこれを試してください

SELECT post_id FROM
(
    SELECT * FROM phpbb_posts
    WHERE topic_id = 144017
    AND post_id != 155352
) A;

これが高速で実行され、少数の行を返す場合は、次のネストされたサブクエリを試してください。

SELECT post_id FROM
(
    SELECT * FROM phpbb_posts
    WHERE topic_id = 144017
    AND post_id != 155352
) A
WHERE MATCH(post_text) AGAINST('http://rapidshare.com/files/5494794/photo.rar');

UPDATE 2012-03-19 13:11 EDT

これの実行時間を比較します。

SELECT count(*) FROM phpbb_posts  WHERE MATCH(post_text) AGAINST ('rapidshare.com') LIMIT 0, 30;

これとともに

SELECT count(*) FROM phpbb_posts WHERE 1 = 1;

実行時間が同じ場合、MATCH句はすべての行で実行されています。前に述べたように、FULLTEXTインデックスを使用すると、MySQLクエリオプティマイザーによって試行および提供された利点がすべて無効になる傾向があります。


それで、topic_idがpost_id混乱するので、私のクエリが実際にテーブル全体をスキャンすると言いたいですか?これらの列(topic_id、post_id)にインデックスがなくてもLIKEクエリが機能するのはなぜですか?なぜMYSQLはtopic_id = 144017 AND post_id != 155352これらの結果をインテリジェントに選択し、ブラウザで表示しないのですか?そして、100k行に私のフルテキスト検索文字列が含まれている場合はどうなりpost_textますか?それらをすべて選択しませんか?
ジェネシス2012年

実際、私はもっと混乱しています。LIKE '%text%'もインデックスを使用しません。つまり、テーブル全体をスキャンするのですが、なぜそんなに高速なのですか?
ジェネシス

私の更新を見てください、あなたはそれを本当に速く解決すると思います。あなたがそれを解決したら、私はあなたに私の担当者をあげます。
ジェネシス

2回目の更新に返信します。2番目のクエリは0.01ミリ秒未満で実行され、最初のクエリは完了しませんでした。「実行時間が同じである場合、MATCH句はすべての行で実行されています」と言ったのはなぜですか。?本来あるべき姿と正反対ではないでしょうか。あなたが見れば、ここで、あなたはこの問題で私だけじゃない表示されます
創世

最初の更新に返信しています。最初のクエリは0.01ミリ秒、0行で実行され、2番目のクエリは「列リストに一致するFULLTEXTインデックスが見つかりません」を返しました。ただし、2つのサブクエリを含むクエリは完全に機能します。
ジェネシス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.