mysql修改字段为⼦查询_对MySQL⼦查询的简单改写优化使⽤过oracle或者其他关系数据库的DBA或者开发⼈员都有这样的经验,在⼦查询上都认为数据库已经做过优化,能够很好的选择驱动表执⾏,然后在把该经验移植到mysql数据库上,但是不幸的是,mysql在⼦查询的处理上有可能会让你⼤失所望,在我们的⽣产系统上就由于碰到了这个问题:
select i_id, sum(i_sell) as i_sell
from table_data
where i_id in (select i_id from table_data where Gmt_create >= '2011-10-07 00:00:00′)
group by i_id;
(备注:sql的业务逻辑可以打个⽐⽅:先查询出10-07号新卖出的100本书,然后在查询这新卖出的100本书在全年的销量情况)。
这条sql之所以出现的性能问题在于mysql优化器在处理⼦查询的弱点,mysql优化器在处理⼦查询的时候,会将将⼦查询改写。通常情况下,我们希望由内到外,先完成⼦查询的结果,然后在⽤⼦查询来驱动外查询的表,完成查询;但是mysql处理为将会先扫描外⾯表中的所有数据,每条数据将会传到⼦查询中与⼦查询关联,如果外表很⼤的话,那么性能上将会出现问题;
针对上⾯的查询,由于table_data这张表的数据有70W的数据,同时⼦查询中的数据较多,有⼤量是重复的,这样就需要关联近70W次,⼤量的关联导致这条sql执⾏了⼏个⼩时也没有执⾏完成,所以我们需要改写sql:
SELECT t2.i_id, SUM(t2.i_sell) AS sold
FROM (SELECT distinct i_id FROM table_data
WHERE gmt_create >= '2011-10-07 00:00:00′) t1, table_data t2
WHERE t1.i_id = t2.i_id GROUP BY t2.i_id;
我们将⼦查询改为了关联,同时在⼦查询中加上distinct,减少t1关联t2的次数;
distinct查询改造后,sql的执⾏时间降到100ms以内。