it-swarm.asia

Mengapa LIKE lebih dari 4x lebih cepat dari MATCH ... MELAWAN indeks FULLTEXT di MySQL?

Saya tidak mendapatkan ini.

Saya punya tabel dengan indeks ini

PRIMARY     post_id
INDEX       topic_id
FULLTEXT    post_text

Tabel memiliki (hanya) 346.000 baris. Saya mencoba melakukan 2 pertanyaan.

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')

membutuhkan waktu 4,05 detik

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%')

membutuhkan waktu 0,027 detik.

EXPLAIN menunjukkan bahwa satu-satunya perbedaan adalah dalam kemungkinan_kunci (fulltext telah menyertakan post_text, LIKE tidak)

Itu sangat aneh.

Ada apa di balik ini? Apa yang terjadi di latar belakang? Bagaimana LIKE bisa begitu cepat saat tidak menggunakan indeks dan FULLTEXT sangat lambat saat menggunakan indeksnya?

UPDATE1:

Sebenarnya sekarang ini membutuhkan waktu sekitar 0,5 detik, mungkin meja dikunci, tetapi tetap saja, ketika saya menghidupkan profil, ini menunjukkan bahwa INISIIALISASI FULLTEXT memerlukan waktu 0,2 detik. Ada apa?

Saya dapat meminta tabel saya dengan LIKE 10x per detik, dengan teks lengkap hanya 2x

UPDATE2:

Mengherankan!

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)

jadi saya bertanya, bagaimana ini mungkin?

Selain itu,

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

sangat lambat. Bisakah teks lengkap rusak?

UPDATE3:

Apa apaan?

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

dibutuhkan waktu 0,27 detik

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

membutuhkan waktu lebih dari 30 detik! Apa yang salah di sini?

12
genesis

Saya pikir masalahnya mungkin berasal dari keberadaan indeks FULLTEXT itu sendiri.

Setiap kali ada kueri yang melibatkan indeks FULLTEXT, Pengoptimal Kueri MySQL cenderung mendorong kueri ke dalam pemindaian tabel penuh. Saya telah melihat ini selama bertahun-tahun. Saya juga menulis posting sebelumnya tentang perilaku paling sepele ini dalam indeks FULLTEXT .

Anda mungkin perlu melakukan dua hal:

  1. refactor kueri sehingga indeks FULLTEXT tidak membuat MySQL Query Optimizer menjadi bingung
  2. Tambahkan indeks tambahan yang akan dengan benar mendukung permintaan refactored

REFACTOR QUERY THE

Ini pertanyaan asli Anda

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') 

Anda harus memperbarui permintaan seperti ini:

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);

BUAT INDEKS BARU

Anda akan memerlukan indeks untuk mendukung subqueryA. Anda sudah memiliki indeks pada topic_id. Anda perlu menggantinya sebagai berikut:

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

Cobalah !!!

UPDATE 2012-03-19 13:08 EDT

Coba yang ini dulu

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

Jika ini berjalan cepat dan mengembalikan sejumlah kecil baris, cobalah subquery bersarang ini:

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

Bandingkan waktu berjalan ini:

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

dengan ini

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

Jika ada waktu berjalan yang sama, maka klausa MATCH dieksekusi pada setiap baris. Seperti yang saya sebutkan sebelumnya, menggunakan indeks FULLTEXT cenderung membatalkan manfaat apa pun yang dicoba dan dikontribusikan oleh Pengoptimal Permintaan MySQL.

2
RolandoMySQLDBA