Ich versuche derzeit, einige Abfragen für einen Daten-Dump 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 ist unglaublich langsam (29 Millionen Zeilen, aber ein Volltextindex):
SELECT *
FROM socomments
WHERE MATCH (Text) AGAINST ('"fixed the post"' IN BOOLEAN MODE)
Also habe ich es profiliert. Die Ergebnisse sind:
|| 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, dauert die FULLTEXT-Initialisierung sehr lange. Ist das normal? Wenn nicht, wie würde ich das beheben?
mysql
innodb
full-text-search
hichris123
quelle
quelle
id_group 2
undid_group 23
. Mit dieser Option durchsuchen Sie Ihre Haupttabelle und begrenzen Ihre Abfrage auf die ID-Bereiche 2.000 bis 2.999 und 23.000 bis 23.999. Natürlich führt die zweite zu mehr Ergebnissen, wenn Sie alle Kommentare verwechseln und neue Schlüsselwortkombinationen erstellen, aber letztendlich sollte dies die ganze Sache beschleunigen. Natürlich verdoppelt es den Speicherplatzbedarf. Neue Kommentare sollten der Gruppentabelle hinzugefügt werden .Antworten:
Andere haben dies als problematisch empfunden
Da die MySQL-Dokumentation über diesen Thread-Status sehr knapp ist
Sie können sich nur auf weniger Daten vorbereiten. Wie ?
VORSCHLAG # 1
Schauen 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 zu sammeln
socomments
. Verbinden Sie dann diese abgerufenen IDs wieder mit dersocomments
Tabelle.Dies könnte zu einem hässlicheren EXPLAIN-Plan führen, aber ich denke, die Profilerstellung wird sich zum Guten wenden. Die Grundidee ist: Wenn Sie eine aggressive FULLTEXT-Suche verwenden, sollten Sie dafür sorgen, dass in dieser
FULLTEXT initialization
Phase die geringste Datenmenge erfasst wird, wodurch die Zeit verkürzt wird.Ich habe das schon oft empfohlen
May 14, 2012
: langsame Abfrage mit Volltext und linkem JoinMar 18, 2012
: Warum ist LIKE mehr als 4x schneller als MATCH ... GEGEN einen FULLTEXT-Index in MySQL?Jan 26, 2012
: MySQL Volltextsuche my.cnf Optimierung :Oct 25, 2011
: FULLTEXT-Index wird im BOOLEAN-MODUS mit der Bedingung 'Anzahl der Wörter' ignoriertVORSCHLAG # 2
Bitte stellen Sie sicher, dass Sie die InnoDB-basierten FULLTEXT-Optionen einstellen, 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 Bytes. Sie haben 29.000.000.000 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 über genügend RAM für größere InnoDB FULLTEXT-Puffer verfügen.
VERSUCHE ES !!!
quelle
SELECT B.* FROM (SELECT id FROM socomments WHERE MATCH (Text) AGAINST ('+"fixed the post"' IN BOOLEAN MODE)) A LEFT JOIN socomments B USING (id);
und prüfen Sie, ob es einen Unterschied macht.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.
in Ihrem speziellen Fall die genaue Phrasefixed the post
muss vorhanden sein.Wenn Sie InnoDB-FULLTEXT-Indizes verwenden, bleiben Abfragen häufig im Status "FULLTEXT-Initialisierung" hängen, wenn Sie eine Abfrage für eine Tabelle mit einer großen Anzahl gelöschter Zeilen durchführen. In der FULLTEXT-Implementierung von InnoDB werden gelöschte Zeilen erst gelöscht, 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
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, sollten Sie regelmäßig OPTIMIZE TABLE für Tabellen mit InnoDB FULLTEXT-Indizes ausführen.
quelle
innodb_optimize_fulltext_only=1
und eineOPTIMIZE
Tabelle kümmert sich tatsächlich um die gelöschten Zeilen "in Wartestellung"? dba.stackexchange.com/questions/174486/…Es gibt einen bestätigten Fehler in MySQL ( gelöschte DOCID werden bei der OPTIMIERUNG von InnoDB-FULLTEXT-Tabellen nicht beibehalten ), der die Leistung bei hohen Löschlasten beeinträchtigt (ohne die Tabelle von Grund auf neu zu erstellen ).
Verwandte .
quelle
Volltextindizes in MySQL unterstützen keine großen Datenmengen, sodass die Suchgeschwindigkeit mit zunehmender Datenmenge sehr schnell abnimmt. Eine der Lösungen besteht darin, externe Volltextsuchmaschinen wie Solr oder Sphinx zu verwenden, die über verbesserte Suchfunktionen (Unterstützung für Relevanzabstimmung und Phrasensuche, integrierte Facetten, Snippets usw.), erweiterte Abfragesyntax und eine wesentlich schnellere Suchgeschwindigkeit in der Mitte bis Mitte verfügen -große Datensätze.
Solr basiert auf der Java-Plattform. Wenn Sie also eine Java-basierte Anwendung ausführen, ist Sphinx in C ++ geschrieben und fungiert wie MySQL als Daemon. Sobald Sie eine externe Engine mit den Daten versorgen, die Sie durchsuchen möchten, können Sie auch einige Abfragen aus MySQL verschieben. Ich kann dir nicht sagen, welche Engine in deinem Fall besser ist, ich verwende hauptsächlich Sphinx und hier ist ein Anwendungsbeispiel: http://astellar.com/2011/12/replacing-mysql-full-text-search-with-sphinx/
quelle