优化SQL查询运行
问题描述:
我有一个查询:优化SQL查询运行
SELECT `l`.`id`, `l`.`headline`, `l`.`description`, `l`.`image`, `l`.`campaign_id`, IF(l.required_impressions=0,0,1) AS sequence, (IFNULL(ROUND(COUNT(DISTINCT(lc.id))/COUNT(DISTINCT(li.id)), 3) * 100, 0) * 0.3) + (l.cost * 0.7) AS `scales`, `c`.`name` AS `campaign`
FROM `app_links` AS `l`
INNER JOIN `app_campaigns` AS `c` ON c.id = l.campaign_id
LEFT JOIN `app_link_clicks` AS `lc` ON lc.link_id = l.id
LEFT JOIN `app_link_impressions` AS `li` ON li.link_id = l.id
LEFT JOIN `app_links_categories` AS `lcat` ON l.id = lcat.link_id
LEFT JOIN `app_links_countries` AS `lcou` ON l.id = lcou.link_id
WHERE lcat.category_id IN(3,7,14)
AND lcou.country_id IN(89,147,124,131,259,197,88)
GROUP BY `l`.`id`
ORDER BY sequence DESC, `scales` DESC
LIMIT 6
的EXPLAIN查询返回:
你有什么想法如何优化查询?现在,它采取〜0.6秒,所以这是相当长的:/
答
只要你指的是lcat
和lcou
的WHERE
子句中是没有意义让他们通过LEFT
被连接加入。
所以我的建议是:对于lcat
- 变化
LEFT JOIN
和lcou
到INNER JOIN
- 移动这两个连接上,因此所有
INNER JOIN
小号都在开始 - 移动
lcat
和lcou
条件对应的ON
条款(这不应该改变任何东西,但会更具可读性) - 创建复合
link_id + country_id
和link_id + category_id
指标 - 正如你所看到的 - MySQL优化顺序改变了的表的连接,所以
app_links
在中间加入,似乎像app_links
是MyISAM数据(它只是基于这样的事实猜测,campaign_id
没有按看起来不像聚簇索引)。如果是这样的 - 尝试添加复合campaign_id + id
指数为它以及
PS:对上面的变化,提供了新的执行计划
PPS:从查询中的所有表
取下提供模式来自查询的'lcat'和'lcou'项,因为它们没有被引用? (或者用一个普通的'JOIN'替换'LEFT JOIN',的确如此) – wildplasser
是否有意使用'lcou.country_id'和'lcou'加入'LEFT JOIN'? 'lcat'的同一个问题。 – zerkms
@wildplasser:它们被用在'WHERE'里。 – zerkms