Neden LIKE, MAÇTAN bir FULLTEXT indeksine karşılık…


12

Bunu anlamıyorum.

Bu dizinleri içeren bir tablo var

PRIMARY     post_id
INDEX       topic_id
FULLTEXT    post_text

Tabloda (sadece) 346 000 satır vardır. 2 sorgu yapmaya çalışıyorum.

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

süre 4.05 saniye sürer

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 saniye sürer.

EXPLAIN, tek farkın fulltextolası_anahtarlarda olduğunu gösterir ( post_text dahil, LIKEdeğil)

Bu gerçekten garip.

Bunun arkasında ne var? Arka planda neler oluyor? LIKEDizin kullanılmadığında nasıl bu kadar hızlı ve dizin kullanılırken FULLTEXT bu kadar yavaş olabilir?

UPDATE1:

Aslında şimdi yaklaşık 0,5 saniye sürüyor, belki masa kilitliydi, ama yine de, profili açtığımda FULLTEXT INITIALIZATION'ın 0.2 saniye sürdüğünü gösteriyor. Naber?

LIKEMasamı saniyede 10x, tam metin sadece 2x ile sorgulayabilirim

Update2:

Sürpriz!

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)

bu yüzden soruyorum, bu nasıl mümkün olabilir?

Bunlara ek olarak,

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

gerçekten yavaş. Tam metin herhangi bir kırık olabilir mi?

Update3:

Ne oluyor be?

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

süre 0.27s sürer

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

30 saniyeden fazla sürüyor! Burada yanlış giden ne?


İkisi arasındaki tepki süreleri birden fazla çalışmada tutarlı mı? Disk önbellekleme ilk "yavaş" test ram içine gereken tüm verileri yükler, böylece ikinci "hızlı" sorgu, iyi hızlı oyuna geliyor düşünmek için cazip.
atxdba

Sorguları yalnızca SQL_NO_CACHE ile test edin .
mgutt

Bu oldukça eski bir soru / cevap. O günden bu yana mysql / mariadb'den ilerleme var mı?
Roman Susi

1
Dikkat: Bu soru-cevap zamanlaması yalnızca MyISAM hakkında konuştuğunu ima eder. InnoDB'ye uygulanabilirliği söz konusudur.
Rick James

@RomanSusi - InnoDB'yi hedefleyen yeni bir soru başlatmak ister misiniz?
Rick James

Yanıtlar:


2

Sorunun FULLTEXT indeksinin kendisinden kaynaklanabileceğini düşünüyorum.

Bir FULLTEXT dizini içeren bir sorgu her açıldığında, MySQL Sorgu Doktoru sorguyu tam tablo taramasına sokma eğilimindedir. Bunu yıllar boyunca gördüm. Ayrıca FULLTEXT dizinlerinde bu en önemsiz davranış hakkında daha önceki bir yazı yazdım .

İki şey yapmanız gerekebilir:

  1. FULLTEXT dizinin MySQL Sorgu Optimize Edici'yi karışıklık durumuna getirmemesi için sorguyu yeniden düzenleyin
  2. Yeniden düzenlenmiş sorguyu doğru şekilde destekleyecek ek bir dizin ekleyin

SOĞUTUCU SORGULAMA

İşte orijinal sorgunuz

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

Sorguyu şu şekilde yeniden düzenlemeniz gerekir:

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

YENİ BİR DİZİN OLUŞTUR

Desteklemek için bir endekse ihtiyacınız olacak subqueryA. Üzerinde zaten bir endeksiniz var topic_id. Aşağıdaki gibi değiştirmeniz gerekir:

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

Bir şans ver !!!

GÜNCELLEME 2012-03-19 13:08 EDT

Önce bunu dene

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

Bu hızlı çalışır ve az sayıda satır döndürürse, bu iç içe geçmiş alt sorguyu deneyin:

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

GÜNCELLEME 2012-03-19 13:11 EDT

Bunun çalışma süresini karşılaştırın:

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

Bununla

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

Çalışma süresi aynıysa, her satırda MATCH yan tümcesi yürütülür. Daha önce bahsettiğim gibi, FULLTEXT dizinlerini kullanmak, MySQL Sorgu Optimize Edici'nin denediği ve katkıda bulunduğu tüm faydaları geçersiz kılma eğilimindedir.


Yani benim sorgu aslında topic_id çünkü tüm tabloyu taramak ve post_idkarıştırır söylemek istiyorum? LIKE sorgusu bu sütunlarda dizin olmasa bile neden çalışıyor (topic_id, post_id)? MYSQL neden topic_id = 144017 AND post_id != 155352sadece bu sonuçları akıllıca seçip tarayıcıyı seçmiyor? Peki ya 100 bin satır tam metin arama dizimi içeriyorsa post_text? Hepsini seçmez mi?
Genesis

Aslında daha da kafam karıştı. '% Text%' GİBİ dizinleri de kullanmaz, tüm tabloyu taradığı anlamına gelir, neden bu kadar hızlı?
Genesis

Lütfen UPDATE'ime bakın , bence çok hızlı çözeceksiniz. Eğer çözerseniz size temsilcimi vereceğim.
genesis

İkinci güncellemenizi yanıtlama. İkinci sorgu 0.01 ms'den daha az bir sürede gerçekleşti, birincisi bitmedi. Neden "Çalışma süresi aynı ise, MATCH yan tümcesi her satırda yürütülüyor" dediniz. ? Olması gerekenin tam tersi değil mi? Eğer bakarsanız burada , ben sadece bu sorunla değilim göreceksiniz
genesis

İlk güncellemenizi yanıtlıyor. İlk sorgu 0.01 ms, 0 satır, ikincisi "sütun listesiyle eşleşen FULLTEXT dizini bulunamıyor" döndürdü. Ancak, 2 alt sorgu ile sorgunuz mükemmel çalışıyor!
genesis
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.