it-swarm.com.de

Die Volltextsuche führt zu einem hohen Zeitaufwand für die 'FULLTEXT-Initialisierung'.

Ich versuche derzeit, einige Abfragen für einen Datendump der Kommentare von Stack Overflow auszuführen. So sieht das Schema aus:

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

Ich habe diese Abfrage für die Tabelle ausgeführt und sie lief unglaublich langsam (sie hat 29 Millionen Zeilen, aber einen Volltextindex):

SELECT *
FROM socomments
WHERE MATCH (Text) AGAINST ('"fixed the post"' IN BOOLEAN MODE)

Also habe ich es profiliert, mit folgenden Ergebnissen:

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

Wie Sie sehen können, verbringt es viel Zeit mit der FULLTEXT-Initialisierung. Ist das normal? Wenn nicht, wie würde ich das beheben?

12
hichris123

Andere haben dies als problematisch empfunden

Da die MySQL-Dokumentation in diesem Thread-Status sehr knapp ist

FULLTEXT-Initialisierung

Der Server bereitet eine Volltextsuche in natürlicher Sprache vor.

ihre einzige Möglichkeit wäre, sich mit weniger Daten vorzubereiten. Wie ?

VORSCHLAG # 1

Sehen Sie sich Ihre Anfrage noch einmal an. Es werden alle Spalten ausgewählt. Ich würde die Abfrage umgestalten, um nur die ID-Spalten von socomments zu sammeln. Fügen Sie dann diese abgerufenen IDs wieder der Tabelle socomments hinzu.

SELECT B.* FROM
(SELECT id FROM socomments
WHERE MATCH (Text) AGAINST ('"fixed the post"' IN BOOLEAN MODE)) A
LEFT JOIN socomments B USING (id);

Dies könnte zu einem hässlicheren EXPLAIN-Plan führen, aber ich denke, die Profilerstellung wird sich zum Besseren ändern. Die Grundidee lautet: Wenn Sie eine aggressive FULLTEXT-Suche durchführen, lassen Sie diese während dieser FULLTEXT initialization - Phase die geringste Datenmenge erfassen, wodurch sich die Zeit verkürzt.

Ich habe dies schon oft empfohlen

VORSCHLAG # 2

Stellen Sie sicher, dass Sie die InnoDB-basierten FULLTEXT-Optionen festlegen, nicht die für MyISAM. Die zwei Optionen, die Sie betreffen sollten, sind

Denken Sie einen Moment darüber nach. Das Textfeld ist VARCHAR (600). Angenommen, der Durchschnitt liegt bei 300 Byte. Sie haben 29 Millionen Millionen von ihnen. Das wäre ein bisschen 8GB. Vielleicht hilft es auch, innodb_ft_cache_size und innodb_ft_total_cache_size zu erhöhen.

Stellen Sie sicher, dass Sie genug RAM für größere InnoDB FULLTEXT-Puffer) haben.

VERSUCHE ES !!!

5
RolandoMySQLDBA

Wenn Sie InnoDB FULLTEXT-Indizes verwenden, hängen Abfragen häufig im Status "FULLTEXT-Initialisierung", wenn Sie eine Tabelle mit einer großen Anzahl gelöschter Zeilen abfragen. In der FULLTEXT-Implementierung von InnoDB werden gelöschte Zeilen erst entfernt, wenn eine nachfolgende OPTIMIZE-Operation für die betroffene Tabelle ausgeführt wird. Siehe: https://dev.mysql.com/doc/refman/5.6/en/innodb-fulltext-index.html

Um Volltextindexeinträge für gelöschte Datensätze zu entfernen, müssen Sie OPTIMIZE TABLE für die indizierte Tabelle mit innodb_optimize_fulltext_only = ON ausführen, um den Volltextindex neu zu erstellen.

Sie können auch die Anzahl der gelöschten, aber nicht gelöschten Datensätze überprüfen, indem Sie information_schema.innodb_ft_deleted abfragen

Um dies zu beheben, sollte OPTIMIZE TABLE regelmäßig für Tabellen mit InnoDB FULLTEXT-Indizes ausgeführt werden.

5
Tyler

Es gibt einen bestätigten Fehler in MySQL ( Gelöschte DOCID werden während der OPTIMIERUNG von InnoDB FULLTEXT-Tabellen nicht beibehalten ), der die Leistung unter starken Löschlasten (ohne die Tabelle von Grund auf neu zu erstellen) panzert.

Verwandte .

1
Riedsio

Volltextindizes in MySQL unterstützen keine großen Datenmengen, sodass die Suchgeschwindigkeit mit zunehmendem Alter Ihres Datasets sehr schnell abnimmt. Eine der Lösungen besteht darin, externe Volltextsuchmaschinen wie Solr oder Sphinx zu verwenden, die eine verbesserte Suchfunktion (Unterstützung der Relevanzoptimierung und Phrasensuche, integrierte Facetten, Snippets usw.), eine erweiterte Abfragesyntax und eine viel schnellere Geschwindigkeit in der Mitte bis Mitte aufweisen -große Datensätze.

Solr basiert auf Java Plattform. Wenn Sie also eine Java-basierte Anwendung ausführen, ist dies für Sie eine natürliche Wahl. Sphinx ist in C++ geschrieben und fungiert als Daemon auf die gleiche Weise wie MySQL Wenn Sie die externe Engine mit den Daten versorgen, die Sie durchsuchen möchten, können Sie auch einige Abfragen aus MySQL verschieben. Ich kann Ihnen nicht sagen, welche Engine in Ihrem Fall besser ist. Ich verwende hauptsächlich Sphinx und hier ein Anwendungsbeispiel: http://astellar.com/2011/12/replacing-mysql-full-text-search-with-sphinx/

0
vfedorkov