私はこれを取得していません。
これらのインデックスを持つテーブルがあります
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は、可能な違いが唯一の違いであることを示しています(fulltext
にはpost_textが含まれていますが、LIKE
は含まれていません)。
それは本当に奇妙です。
この背後にあるものは何ですか?バックグラウンドで何が起こっていますか?インデックスを使用していないときにLIKE
を高速にして、インデックスを使用しているときにFULLTEXTを低速にするにはどうすればよいですか?
実際には約0.5秒かかりますが、テーブルがロックされている可能性がありますが、プロファイリングをオンにすると、FULLTEXT INITIALIZATIONに0.2秒かかったことが示されます。調子はどう?
LIKE
で1秒あたり10倍、フルテキストは2倍でテーブルをクエリできます
驚き!
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')
本当に遅いです。全文が壊れている可能性はありますか?
なんてこったい?
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秒以上かかります!ここで何が問題になっていますか?
問題はFULLTEXTインデックス自体の存在に起因していると思います。
FULLTEXTインデックスを含むクエリがあるたびに、MySQLクエリオプティマイザーはクエリをフルテーブルスキャンに変換する傾向があります。私は何年にもわたってこれを見てきました。 FULLTEXTインデックスにおけるこの最も些細な動作についての以前の投稿も書きました 。
次の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;
試してみる !!!
まずこれを試してください
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');
この実行時間を比較します。
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クエリオプティマイザーによって試行および提供された利点がすべて無効になる傾向があります。