J'essaie actuellement d'exécuter des requêtes sur un vidage de données des commentaires de Stack Overflow. Voici à quoi ressemble le schéma:
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
J'ai exécuté cette requête sur la table, et elle a été incroyablement lente (elle contient 29 millions de lignes, mais elle a un index de texte intégral):
SELECT *
FROM socomments
WHERE MATCH (Text) AGAINST ('"fixed the post"' IN BOOLEAN MODE)
Je l'ai donc profilé, dont les résultats sont:
|| 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 ||
Comme vous pouvez le voir, il passe beaucoup de temps à l'initialisation FULLTEXT. Est-ce normal? Sinon, comment pourrais-je le réparer?
mysql
innodb
full-text-search
hichris123
la source
la source
id_group 2
etid_group 23
. Avec cela, votre recherche à l'intérieur de votre table principale et limitez votre requête aux plages d'ID 2.000 à 2.999 et 23.000 à 23.999. Bien sûr, le 2e produira plus de résultats au fur et à mesure que vous mélangerez tous les commentaires en créant de nouvelles combinaisons de mots clés, mais finalement cela devrait accélérer le tout. Bien sûr, cela double l'utilisation de l'espace disque. De nouveaux commentaires devraient être CONCAT'és à la table de groupe.Réponses:
D'autres ont trouvé que c'était une situation gênante
Étant donné que la documentation MySQL est très concise sur cet état de thread
votre seul recours serait de vous préparer avec moins de données. Comment ?
SUGGESTION # 1
Examinez à nouveau votre requête. Il sélectionne toutes les colonnes. Je voudrais refactoriser la requête pour collecter uniquement les colonnes id
socomments
. Ensuite, joignez ces identifiants récupérés à lasocomments
table.Cela pourrait produire un plan EXPLAIN plus laid mais je pense que le profilage changera pour le mieux. L'idée de base est la suivante: si vous avez une recherche FULLTEXT agressive, faites-la recueillir le moins de données pendant cette
FULLTEXT initialization
phase, réduisant ainsi le temps.Je l'ai déjà recommandé plusieurs fois
May 14, 2012
: requête lente avec fulltext et jointure gaucheMar 18, 2012
: Pourquoi LIKE est plus de 4x plus rapide que MATCH ... AGAINST sur un index FULLTEXT dans MySQL?Jan 26, 2012
: Mysql fulltext search optimisation my.cnf :Oct 25, 2011
: Index FULLTEXT ignoré en MODE BOOLÉEN avec conditionnel 'nombre de mots'SUGGESTION # 2
Veuillez vous assurer que vous définissez les options FULLTEXT basées sur InnoDB, pas celles pour MyISAM. Les deux options qui devraient vous préoccuper sont
Pensez-y un instant. Le champ de texte est VARCHAR (600). Disons que la moyenne est de 300 octets. Vous en avez 29 000 000 millions. Ce serait un peu 8 Go. Peut-être que l'augmentation de innodb_ft_cache_size et innodb_ft_total_cache_size peut également aider.
Assurez-vous que vous disposez de suffisamment de RAM pour les plus grands tampons InnoDB FULLTEXT.
ESSAIE !!!
la source
SELECT B.* FROM (SELECT id FROM socomments WHERE MATCH (Text) AGAINST ('+"fixed the post"' IN BOOLEAN MODE)) A LEFT JOIN socomments B USING (id);
et voyez si cela fait une différence.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.
Dans votre cas particulier, la phrase exactefixed the post
doit exister.Si vous utilisez des index InnoDB FULLTEXT, les requêtes se bloquent souvent dans l'état "FULLTEXT initialization" si vous interrogez une table contenant un grand nombre de lignes supprimées. Dans l'implémentation FULLTEXT d'InnoDB, les lignes supprimées ne sont pas élaguées jusqu'à ce qu'une opération OPTIMIZE ultérieure soit exécutée sur la table affectée. Voir: https://dev.mysql.com/doc/refman/5.6/en/innodb-fulltext-index.html
On peut également inspecter le nombre d'enregistrements supprimés mais non purgés en interrogeant information_schema.innodb_ft_deleted
Pour résoudre ce problème, il convient d'exécuter régulièrement OPTIMIZE TABLE sur des tables avec des index InnoDB FULLTEXT.
la source
innodb_optimize_fulltext_only=1
et uneOPTIMIZE
table prend réellement en charge les lignes supprimées "en attente"? dba.stackexchange.com/questions/174486/…Il y a un bogue confirmé dans MySQL (les DOCID supprimés ne sont pas conservés lors de l'OPTIMISATION des tables InnoDB FULLTEXT ) qui réservent les performances sous de lourdes charges de suppression (sans reconstruire la table à partir de zéro).
Connexes .
la source
Les index de texte intégral dans MySQL ne sont pas conçus pour prendre en charge de grandes quantités de données, donc la vitesse de recherche diminue assez rapidement à mesure que votre ensemble de données grandit. L'une des solutions consiste à utiliser des moteurs de recherche en texte intégral externes comme Solr ou Sphinx qui ont des fonctionnalités de recherche améliorées (optimisation de la pertinence et prise en charge de la recherche de phrases, facettes intégrées, extraits de code, etc.), syntaxe de requête étendue et vitesse beaucoup plus rapide à mi-chemin -grands ensembles de données.
Solr est basé sur la plate-forme Java, donc si vous exécutez une application basée sur Java est un choix naturel pour vous, Sphinx est écrit en C ++ et agit comme un démon de la même manière que MySQL. Dès que vous alimentez le moteur externe avec les données que vous souhaitez rechercher, vous pouvez également déplacer certaines requêtes hors de MySQL. Je ne peux pas vous dire quel moteur est meilleur dans votre cas, j'utilise principalement Sphinx et voici un exemple d'utilisation: http://astellar.com/2011/12/replacing-mysql-full-text-search-with-sphinx/
la source