Optimize SQL Query

I have problem with optimize this 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

Now, this query using ^ 20 seconds. How to optimize this?

EXPLAIN gives this:

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

This is example server with my data:

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

Looks like your db is dead. Getting rid of inner query is the key part to optimization. Please try this (not tested) query:

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

To further optimize your query you may also split getting articles with newest version from full text search as the latter is the most expensive. This can be done by subquerying (also not tested on your 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

The first thing I noticed in your DB is that you don't have an index on xv_articleindex . adressinsql . Add it, and it should significantly improve the query performance. Also, one table is MyISAM, whereas another one is InnoDb. Use one engine(in general, I'd recommend InnoDB)

链接地址: http://www.djcxy.com/p/62448.html

上一篇: 查询优化(WHERE,GROUP BY,LEFT JOIN)

下一篇: 优化SQL查询