2011-01-15 3 views
4

J'ai problème avec optimize cette requête:Optimize SQL Query

SET @SEARCH = "dokumentalne"; 

SELECT SQL_NO_CACHE 
`AA`.`version` AS `Version` , 
`AA`.`contents` AS `Contents` , 
`AA`.`idarticle` AS `AdressInSQL` , 
`AA` .`topic` AS `Topic` , 
MATCH (`AA`.`topic` , `AA`.`contents`) AGAINST (@SEARCH) AS `Relevance` , 
`IA`.`url` AS `URL` 
FROM `xv_article` AS `AA` 
INNER JOIN `xv_articleindex` AS `IA` ON (`AA`.`idarticle` = `IA`.`adressinsql`) 
INNER JOIN (
    SELECT `idarticle` , MAX(`version`) AS `version` 
    FROM `xv_article` 
    WHERE MATCH (`topic` , `contents`) AGAINST (@SEARCH) 
    GROUP BY `idarticle` 
) AS `MG` 
ON (`AA`.`idarticle` = `MG`.`idarticle`) 
WHERE `IA`.`accepted` = "yes" 
AND `AA`.`version` = `MG`.`version` 
ORDER BY `Relevance` DESC 
LIMIT 0 , 30 

Maintenant, cette requête en utilisant^20 secondes. Comment optimiser cela?

EXPLIQUER donne ceci:

 
1 PRIMARY AA ALL NULL NULL NULL NULL 11169 Using temporary; Using filesort 
1 PRIMARY ALL NULL NULL NULL NULL 681 Using where 
1 PRIMARY IA ALL accepted NULL NULL NULL 11967 Using where 
2 DERIVED xv_article fulltext topic topic 0  1 Using where; Using temporary; Using filesort

Ceci est par exemple serveur avec mes données:

 
user: bordeux_4prog 
password: 4prog 
phpmyadmin: http://phpmyadmin.bordeux.net/ 
chive: http://chive.bordeux.net/ 
+9

Voulez-vous * vraiment * que ces détails en direct sur Internet pour tout voir? –

+4

+1 pour configurer le serveur de test pour SO crowd – too

+0

Vous savez que l'utilisation de \ backtags n'est nécessaire que si vous voulez utiliser une instruction MySQL comme variable ou table ou quelque chose comme ça (par exemple \ 'order \')? Taper tout avec \ 's est et semble très ennuyeux imho. – Alec

Répondre

1

On dirait que votre db est mort. Se débarrasser de la requête interne est la partie clé de l'optimisation. S'il vous plaît essayer (non testé) requête:

SET @SEARCH = "dokumentalne"; 

SELECT SQL_NO_CACHE 
    aa.idarticle AS `AdressInSQL`, 
    aa.contents AS `Contents`, 
    aa.topic AS `Topic`, 
    MATCH(aa.topic , aa.contents) AGAINST (@SEARCH) AS `Relevance`, 
    ia.url AS `URL`, 
    MAX(aa.version) AS `Version` 
FROM 
    xv_article AS aa, 
    xv_articleindex AS ia 
WHERE 
    aa.idarticle = ia.adressinsql 
    AND ia.accepted = "yes" 
    AND MATCH(aa.topic , aa.contents) AGAINST (@SEARCH) 
GROUP BY 
    aa.idarticle, 
    aa.contents, 
    `Relevance`, 
    ia.url 
ORDER BY 
    `Relevance` DESC 
LIMIT 
    0, 30 

Pour optimiser davantage votre requête, vous pouvez diviser obtenir des articles avec toute dernière version de recherche en texte intégral que celui-ci est le plus cher. Cela peut être fait par subquerying (également non testé sur votre db):

SELECT SQL_NO_CACHE 
    iq.idarticle AS `AdressInSQL`, 
    iq.topic AS `Topic`, 
    iq.contents AS `Contents`, 
    iq.url AS `URL`, 
    MATCH(iq.topic, iq.contents) AGAINST (@SEARCH) AS `Relevance` 
FROM (
    SELECT 
    a.idarticle, 
    a.topic, 
    a.contents, 
    i.url, 
    MAX(a.version) AS version 
    FROM 
    xv_article AS a, 
    xv_articleindex AS i 
    WHERE 
    i.accepted = "yes" 
    AND a.idarticle = i.adressinsql 
    GROUP BY 
    a.idarticle AS id, 
    a.topic, 
    a.contents, 
    i.url 
) AS iq 
WHERE 
    MATCH(iq.topic, iq.contents) AGAINST (@SEARCH) 
ORDER BY 
    `Relevance` DESC 
LIMIT 
    0, 30 
1

La première chose que je remarque dans votre DB est que vous ne disposez pas d'un index sur xv_articleindex. adressinsql. Ajoutez-le et cela devrait améliorer considérablement les performances de la requête. En outre, une table est MyISAM, tandis qu'une autre est InnoDb. Utilisez un moteur (en général, je recommanderais InnoDB)

+0

je ne peux pas utiliser innodb, car InnoDB n'a pas de module de recherche plein texte. – bordeux

+0

bien, changez tous les deux en MyISAM. – a1ex07