Obecnie próbuję uruchomić zapytania dotyczące zrzutu danych komentarzy przepełnienia stosu. Oto jak wygląda schemat:
CREATE TABLE `socomments` (
`Id` int(11) NOT NULL,
`PostId` int(11) NOT NULL,
`Score` int(11) DEFAULT NULL,
`Text` varchar(600) NOT NULL,
`CreationDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`UserId` int(11) NOT NULL,
PRIMARY KEY (`Id`),
KEY `idx_socomments_PostId` (`PostId`),
KEY `CreationDate` (`CreationDate`),
FULLTEXT KEY `Text` (`Text`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Uruchomiłem to zapytanie względem tabeli i działało ono niezwykle wolno (ma 29 milionów wierszy, ale ma indeks pełnotekstowy):
SELECT *
FROM socomments
WHERE MATCH (Text) AGAINST ('"fixed the post"' IN BOOLEAN MODE)
Więc profilowałem to, czego rezultatem są:
|| Status || Duration ||
|| starting || 0.000058 ||
|| checking permissions || 0.000006 ||
|| Opening tables || 0.000014 ||
|| init || 0.000019 ||
|| System lock || 0.000006 ||
|| optimizing || 0.000007 ||
|| statistics || 0.000013 ||
|| preparing || 0.000005 ||
|| FULLTEXT initialization || 207.1112 ||
|| executing || 0.000009 ||
|| Sending data || 0.000856 ||
|| end || 0.000004 ||
|| query end || 0.000004 ||
|| closing tables || 0.000006 ||
|| freeing items || 0.000059 ||
|| logging slow query || 0.000037 ||
|| cleaning up || 0.000046 ||
Jak widać, inicjowanie FULLTEXT zajmuje dużo czasu. Czy to normalne? Jeśli nie, jak bym to naprawić?
mysql
innodb
full-text-search
hichris123
źródło
źródło
id_group 2
iid_group 23
. Dzięki temu Twoje wyszukiwanie w głównej tabeli i ograniczenie zapytania do zakresów identyfikatorów od 2.000 do 2.999 i 23.000 do 23.999. Oczywiście 2. miejsce przyniesie więcej wyników w miarę potrzeb, gdy pomieszasz wszystkie komentarze, tworząc nowe kombinacje słów kluczowych, ale w końcu powinno to przyspieszyć całość. Oczywiście podwaja wykorzystanie miejsca na dysku. Nowe komentarze powinny być ZAWSZE w tabeli grup.Odpowiedzi:
Inni uznali tę sytuację za kłopotliwą
Ponieważ dokumentacja MySQL jest bardzo zwięzła w tym stanie wątku
jedynym wyjściem będzie przygotowanie się z mniejszą ilością danych. W jaki sposób ?
SUGESTIA # 1
Spójrz ponownie na zapytanie. Zaznacza wszystkie kolumny. Dokonałbym refaktoryzacji zapytania, aby zebrać tylko kolumny id
socomments
. Następnie dołącz odzyskane identyfikatory z powrotem dosocomments
tabeli.Może to stworzyć brzydszy plan WYJAŚNIJ, ale myślę, że profilowanie zmieni się na lepsze. Podstawowa idea jest taka: jeśli masz agresywne wyszukiwanie PEŁNOTEKSTOWE, spraw, aby gromadziło najmniej danych w tej
FULLTEXT initialization
fazie, skracając w ten sposób czas.Polecałem to wiele razy wcześniej
May 14, 2012
: wolne zapytanie z pełnym tekstem i lewym złączeniemMar 18, 2012
: Dlaczego LIKE jest ponad czterokrotnie szybszy niż MATCH ... AGAINST w indeksie FULLTEXT w MySQL?Jan 26, 2012
: Przeszukiwanie pełnego tekstu MySQL optymalizacja my.cnf :Oct 25, 2011
: Indeks FULLTEXT jest ignorowany w TRYBIE BOOLEAN z warunkową liczbą słówSUGESTIA # 2
Upewnij się, że ustawiasz opcje FULLTEXT-a oparte na InnoDB, a nie te dla MyISAM. Dwie opcje, którymi powinieneś się martwić to:
Pomyśl o tym przez chwilę. Pole tekstowe to VARCHAR (600). Powiedzmy, że średnia to 300 bajtów. Masz ich 29 000 000 milionów. To by było trochę 8 GB. Być może zwiększenie innodb_ft_cache_size i innodb_ft_total_cache_size może również pomóc.
Upewnij się, że masz wystarczającą ilość pamięci RAM dla większych buforów InnoDB FULLTEXT.
SPRÓBUJ !!!
źródło
SELECT B.* FROM (SELECT id FROM socomments WHERE MATCH (Text) AGAINST ('+"fixed the post"' IN BOOLEAN MODE)) A LEFT JOIN socomments B USING (id);
i sprawdź, czy to robi różnicę.A leading or trailing plus sign indicates that this word must be present in each row that is returned. InnoDB only supports leading plus signs.
W twoim konkretnym przypadkufixed the post
musi istnieć dokładna fraza .Jeśli korzystasz z indeksów InnoDB FULLTEXT, zapytania często zawieszają się w stanie „Inicjalizacja FULLTEXT”, jeśli wysyłasz zapytania do tabeli z dużą liczbą usuniętych wierszy. W implementacji FULLTEXT firmy InnoDB usunięte wiersze nie są przycinane, dopóki nie zostanie uruchomiona kolejna operacja OPTIMIZE w odniesieniu do tabeli, której dotyczy problem. Zobacz: https://dev.mysql.com/doc/refman/5.6/en/innodb-fulltext-index.html
Można również sprawdzić liczbę usuniętych, ale nie wyczyszczonych rekordów, sprawdzając informacje_schema.innodb_ft_deleted
Aby rozwiązać ten problem, należy regularnie uruchamiać OPTYMALIZACJĘ TABELI dla tabel z indeksami InnoDB FULLTEXT.
źródło
innodb_optimize_fulltext_only=1
aOPTIMIZE
tabela faktycznie zajmuje się usuniętymi wierszami „w oczekiwaniu”? dba.stackexchange.com/questions/174486/…W MySQL potwierdzono błąd ( usunięte DOCID nie są utrzymywane podczas OPTYMALIZACJI tabel FULLTEXT InnoDB ), że wydajność zbiorników pod dużym obciążeniem usuwania (bez odbudowywania tabeli od zera).
Związane .
źródło
Indeksy pełnotekstowe w MySQL nie są zaprojektowane do obsługi dużych ilości danych, więc szybkość wyszukiwania spada dość szybko, gdy Twój zbiór danych rośnie. Jednym z rozwiązań jest użycie zewnętrznych wyszukiwarek pełnotekstowych, takich jak Solr lub Sphinx, które mają ulepszoną funkcjonalność wyszukiwania (dostrajanie trafności i wsparcie wyszukiwania wyrażeń, wbudowane aspekty, fragmenty itp.) Rozszerzona składnia zapytań i znacznie szybsza prędkość od średniej do średniej -duże zestawy danych.
Solr jest oparty na platformie Java, więc jeśli uruchomisz aplikację opartą na Javie, będzie to dla ciebie naturalny wybór, Sphinx jest napisany w C ++ i działa jako demon w taki sam sposób jak MySQL. Jak tylko podasz silnikowi zewnętrznemu dane, które chcesz przeszukać, możesz również przenieść niektóre zapytania z MySQL. Nie mogę powiedzieć, który silnik jest lepszy w twoim przypadku, używam głównie Sphinx, a oto przykład użycia: http://astellar.com/2011/12/replacing-mysql-full-text-search-with-sphinx/
źródło