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)
上一篇: 查询优化(WHERE,GROUP BY,LEFT JOIN)
下一篇: 优化SQL查询