Nie rozumiem tego.
Mam tabelę z tymi indeksami
PRIMARY post_id
INDEX topic_id
FULLTEXT post_text
Tabela ma (tylko) 346 000 wierszy. Próbuję wykonać 2 zapytania.
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')
trwa 4,05 sekundy
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%')
zajmuje 0,027 sekundy.
EXPLAIN pokazuje, że jedyną różnicą są możliwe fulltext
klucze ( zawiera tekst post_tekst, LIKE
nie ma)
To naprawdę dziwne.
Co za tym stoi? Co dzieje się w tle? Jak może LIKE
być tak szybko, gdy nie używa się indeksu, a FULLTEXT tak wolno, gdy używa się jego indeksu?
AKTUALIZACJA 1:
Właściwie zajmuje to teraz około 0,5 sekundy, być może stół został zablokowany, ale mimo to po włączeniu profilowania pokazuje, że INICJALIZACJA PEŁNOTEKSTOWA trwała 0,2 sekundy. Co tam?
Mogę przeszukiwać tabelę LIKE
10 razy na sekundę, a pełny tekst tylko 2x
AKTUALIZACJA 2:
Niespodzianka!
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)
więc pytam, jak to możliwe?
Dodatkowo,
SELECT count(*) FROM phpbb_posts WHERE MATCH(post_text) AGAINST ('rapidshare.com')
jest naprawdę wolny. Czy pełny tekst może być uszkodzony?
AKTUALIZACJA 3:
Co do cholery?
SELECT forum_id, post_id, topic_id, post_text FROM phpbb_posts WHERE MATCH(post_text) AGAINST ('rapidshare.com') LIMIT 0, 30;
trwa 0,27 sek
SELECT count(*) FROM phpbb_posts WHERE MATCH(post_text) AGAINST ('rapidshare.com') LIMIT 0, 30;
zajmuje ponad 30 sekund! Co tu idzie nie tak?
źródło
Odpowiedzi:
Myślę, że problem może wynikać z obecności samego indeksu FULLTEXT.
Za każdym razem, gdy występuje zapytanie dotyczące indeksu FULLTEXT, MySQL Query Optimizer dąży do rozbicia zapytania na pełny skan tabeli. Widziałem to przez lata. Napisałem też wcześniejszy post na temat tego najbardziej błahego zachowania w indeksach FULLTEXT .
Może być konieczne zrobienie dwóch rzeczy:
REFAKTOR ZAPYTANIA
Oto twoje oryginalne zapytanie
Konieczne będzie przefiltrowanie zapytania w następujący sposób:
STWÓRZ NOWY INDEKS
Będziesz potrzebował indeksu do obsługi
subqueryA
. Masz już indeks natopic_id
. Musisz go wymienić w następujący sposób:Spróbuj !!!
AKTUALIZACJA 2012-03-19 13:08 EDT
Spróbuj tego pierwszego
Jeśli działa to szybko i zwraca niewielką liczbę wierszy, spróbuj tego zagnieżdżonego podzapytania:
AKTUALIZACJA 2012-03-19 13:11 EDT
Porównaj czas działania tego:
z tym
Jeśli czas wykonywania jest taki sam, klauzula MATCH jest wykonywana w każdym wierszu. Jak już wspomniałem wcześniej, użycie indeksów FULLTEXT ma tendencję do unieważniania wszelkich korzyści, do których spróbował i wniósł wkład MySQL Query Optimizer.
źródło
post_id
myli ją? Dlaczego zapytanie LIKE działa nawet bez indeksu w tych kolumnach (topic_id, post_id)? Dlaczego MYSQL nie tylko inteligentnie wybiera,topic_id = 144017 AND post_id != 155352
a następnie przegląda te wyniki? A co, jeśli 100 000 wierszy zawiera mój ciąg wyszukiwania pełnotekstowegopost_text
? Czy nie wybrałby ich wszystkich?