码迷,mamicode.com
首页 > 数据库 > 详细

mysql 语句优化一列

时间:2016-07-17 02:42:10      阅读:265      评论:0      收藏:0      [点我收藏+]

标签:mysql 优化   sql 优化   

优化前语句:

SELECT

ifnull(s.mileage, -1) as mile,

s.fuel_hkm as val,

t.fhkm_rank as rank,

ifnull((select u.photo from app_user u where u.user_id = t.user_id  limit 1),‘‘) as path,

case when s.car_id = ‘***********‘ then 0

else 1 end as self,

ifnull((

SELECT

case 

when ifnull(u.nickname, ‘‘) != ‘‘ then u.nickname 

when ifnull(u.username, ‘‘) != ‘‘ then u.username 

when ifnull(u.customer_number, ‘‘) != ‘‘ then u.customer_number

else u.mobile END as uname

FROM

app_user u

WHERE

u.user_id = t.user_id

LIMIT 1

),‘‘)  as manname,

ifnull((select case when ifnull(c.nickname,‘‘) != ‘‘ then c.nickname else REPLACE(c.lisence,SUBSTR(c.lisence,3,3),‘***‘) end from app_car c where c.car_id = t.car_id limit 1),‘‘)  as carname

FROM

app_car_sum_7daily s,

app_rank_ka t

WHERE

 t.date = ‘2016-07-12‘

 and t.date = s.date

 and t.car_id = s.car_id

 and s.fuel_hkm > 0

 and t.fhkm_rank > 0

ORDER BY rank,self,convert(manname using gbk) limit 10


优化后语句:

select * from (

select 

ifnull(s.mileage, -1) as mile,

s.fuel_hkm as val,

t.fhkm_rank as rank,

ifnull(u.photo,‘‘) as path,

case when s.car_id = ‘***********‘ then 0

else 1 end as self,

case

when ifnull(u.nickname,‘‘) != ‘‘ then u.nickname

when ifnull(u.username,‘‘) != ‘‘ then u.username

when ifnull(u.customer_number,‘‘) != ‘‘ then u.customer_number

else ifnull(u.mobile,‘‘) end as manname,

case

when ifnull(c.nickname,‘‘) != ‘‘ then c.nickname

else ifnull(REPLACE(c.lisence,SUBSTR(c.lisence,3,3),‘***‘),‘‘) end as carname

from

app_rank_ka t 

join app_car_sum_7daily s on (s.date = t.date and s.car_id = t.car_id and s.fuel_hkm > 0)

join app_user u on (u.user_id = t.user_id)

join app_car c on (c.car_id = t.car_id)

where t.date = ‘2016-07-12‘ and t.fhkm_rank > 0 

ORDER BY rank limit 200) a order by rank,self,convert(manname using gbk) limit 10;



优化方法:

1、去子查询优化为join查询

2、子查询带limit 1的表链接键都为主键,所以不再需要limit 1

3、app_rank_ka(t)表,对别名为rank的字段和date字段建联合索引优化内层排序idx_date_rank

4、在不对sql业务进行判断及变更的情况下采用折中的办法,先根据rank limit 200条或者觉得合适的条数只要不是非常多,再进行业务排序

5、嵌套链接索引都很合理,该点无优化空间

优化原理:

1、该sql慢的主要原因在于order by 多个字段

2、mysql的order by只是利用sort_buffer做第一个字段的排序,后面的字段会在临时表中进行,并且计算量很大,根据optimizer_trace跟踪本来只有4万多条数据在排序三个字段之后扫描了14万次以上才完成

3、mysql的order by优化算法有两个,一种sort_buffer存的数据为(sort_key1,sort_key2,sort_key3,row_id)排序完成还需回表查询数据,另一种为(sort_key1,sort_key2,sort_key3,key1 value,key2 value,key3 value....)包含所有需求字段数据,在数据不超过阈值(max_length_for_sort_data)时默认都会采用第二种优化方式

3、上面sql采用的方式就利用了索引先优化从表里面取数据时的排序,限制了200条作为外层的排序数据,不过这也建立了一个临时表,鉴于数据长度不是很大,在数据量不多时效率影响有限,在外层利用三个字段进行排序不管是使用那一种sort算法查找数据都是很高效的

4、关联子查询在mysql查询优化器中处理都不是很如意,优化为join不仅避免优化器选择的问题也可以降低优化器的消耗时间


优化前后执行时间对比:

优化前:

|        1 | 8.94656525 |

|        2 | 8.77086475 |

优化后:

|        3 | 0.00527075 |

|        4 | 0.00513025 |


该sql有5种order by排序规则的查询,优化方式相同!!!!!,分别建date和这5个字段建立联合索引,可以删除现有的date单列所以,因为date字段为时间列不会做更新操作,即使该5个字段经常更新页之间数据移动也不会发生页分裂的情况,又因为mysql提供change_buffer为辅助索引提供内存缓冲,所以新建(5-1)个索引的维护成本完全可以接受


PS:如果业务上能修改排序条件,可以只使用子查询就行,效率更高,通常尽量只使用一个字段排序,在数据量大时多字段的排序耗时成倍增长

本文出自 “D调de默默” 博客,谢绝转载!

mysql 语句优化一列

标签:mysql 优化   sql 优化   

原文地址:http://xiaozhong991.blog.51cto.com/2354914/1826990

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!