Je ne comprends pas ça.
J'ai une table avec ces index
PRIMARY post_id
INDEX topic_id
FULLTEXT post_text
La table a (seulement) 346 000 lignes. J'essaie d'effectuer 2 requêtes.
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')
prend 4,05 secondes tandis que
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%')
prend 0,027 seconde.
EXPLAIN montre que la seule différence est dans possible_keys ( fulltext
a post_text inclus, LIKE
ne le fait pas)
C'est vraiment étrange.
Qu'est-ce qui se cache derrière ça? Que se passe-t-il en arrière-plan? Comment peut-on LIKE
être si rapide quand on n'utilise pas index et FULLTEXT si lent quand on utilise son index?
MISE À JOUR1:
En fait, cela prend maintenant environ 0,5 seconde, peut-être que la table était verrouillée, mais quand même, lorsque j'allume le profilage, cela montre que FULLTEXT INITIALIZATION a pris 0,2 seconde. Quoi de neuf?
Je peux interroger ma table avec LIKE
10x par seconde, avec fulltext seulement 2x
MISE À JOUR2:
Surprise!
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)
donc je demande, comment est-ce possible?
Aditionellement,
SELECT count(*) FROM phpbb_posts WHERE MATCH(post_text) AGAINST ('rapidshare.com')
est vraiment lent. Peut être en texte intégral tout cassé?
MISE À JOUR3:
Que se passe-t-il?
SELECT forum_id, post_id, topic_id, post_text FROM phpbb_posts WHERE MATCH(post_text) AGAINST ('rapidshare.com') LIMIT 0, 30;
prend 0,27 s tout
SELECT count(*) FROM phpbb_posts WHERE MATCH(post_text) AGAINST ('rapidshare.com') LIMIT 0, 30;
prend plus de 30 secondes! Qu'est-ce qui ne va pas ici?
la source
Réponses:
Je pense que le problème peut provenir de la présence de l'index FULLTEXT lui-même.
Chaque fois qu'il y a une requête impliquant un index FULLTEXT, MySQL Query Optimizer a tendance à détraquer la requête dans une analyse complète de la table. Je l'ai vu au fil des ans. J'ai également écrit un article précédent sur ce comportement le plus insignifiant dans les index FULLTEXT .
Vous devrez peut-être faire deux choses:
RÉFLÉCHIR LA REQUÊTE
Voici votre requête d'origine
Vous devrez refactoriser la requête comme ceci:
CRÉER UN NOUVEL INDICE
Vous aurez besoin d'un index à supporter
subqueryA
. Vous avez déjà un index surtopic_id
. Vous devez le remplacer comme suit:Essaie !!!
MISE À JOUR 2012-03-19 13:08 EDT
Essayez celui-ci en premier
Si cela s'exécute rapidement et renvoie un petit nombre de lignes, essayez cette sous-requête imbriquée:
MISE À JOUR 2012-03-19 13:11 EDT
Comparez le temps d'exécution de ceci:
avec ça
Si le temps d'exécution est le même, la clause MATCH est exécutée sur chaque ligne. Comme je l'ai mentionné précédemment, l'utilisation des index FULLTEXT tend à annuler tous les avantages tentés et apportés par MySQL Query Optimizer.
la source
post_id
confond? Pourquoi la requête LIKE fonctionne-t-elle même sans avoir d'index sur ces colonnes (topic_id, post_id)? Pourquoi MYSQL ne sélectionne-t-il pas simplement intelligemmenttopic_id = 144017 AND post_id != 155352
, puis ne fait-il que naviguer dans ces résultats? Et si 100k lignes incluent ma chaîne de recherche en texte intégral danspost_text
? Ne les sélectionnerait-il pas tous?