mysql性能问题

时间:2012-06-01 17:46:10

标签: mysql query-optimization

我有一个简单的查询,没有连接,运行速度很慢(20秒+)。查询的表有大约400k行,并且where子句中使用的所有列都被编入索引。

SELECT deals.id, deals.title, 
       deals.amount_sold * deals.sale_price   AS total_sold_total
FROM deals  
WHERE deals.country_id = 33 
  AND deals.target_approved = 1 
  AND deals.target_active = 1 
  AND deals.finished_at >= '2012-04-01' 
  AND deals.started_at <= '2012-04-30'
ORDER BY total_sold_total DESC 
LIMIT 0, 10

我上周以来一直在努力解决这个问题,请我帮忙:)

更新1

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  deals   index_merge NewIndex3,finished_at_index,index_deals_on_country_id,index_deals_on_target_active,index_deals_on_target_approved   index_deals_on_target_active,index_deals_on_target_approved,index_deals_on_country_id   2,2,5   \N  32382   Using intersect(index_deals_on_target_active,index_deals_on_target_approved,index_deals_on_country_id); Using where; Using filesort

1 个答案:

答案 0 :(得分:3)

要改进选择,请按照指定的顺序使用WHERE子句中的列创建以下复合索引:

(country_id, target_approved, target_active, finished_at)
(country_id, target_approved, target_active, started_at)

首先需要具有更高基数的列,其中范围最后。 MySQL不能utilize any key parts past the first range,这就是为什么我们有两个单独的索引在WHERE子句(>=<=)范围内分歧。

如果MySQL没有通过索引合并使用这两个索引,那么您可以考虑删除其中一个索引。

不幸的是,在订购行之前,MySQL仍然必须返回所有行,计算total_sold_total。换句话说,MySQL必须在检索完整个数据集后手动对行进行排序。

排序所需的时间与结果集的大小成正比。

无法使用LIMIT优化,因为在排序后应用了LIMIT。

不幸的是,在WHERE子句中使用范围会阻止您将预先计算的total_sold_total列添加到索引的末尾,以便按顺序返回结果,这将阻止手动排序。