zoukankan      html  css  js  c++  java
  • MySql优化浅析

     

    优化点:合理的使用索引,可以大幅度提升sql查询效率,特别查询的表的数据量大的时候,效果明显。一.引言

      公司的产品XX出行上线正式运营,随着数据量的变大,司机2000+,日订单1万+,注册乘客26W+,MySql的一些语句查询效率低下,严重的达到10秒级别以上,严重的影响系统服务。故公司安排我负责数据库方面的工作。(吐槽,公司不是很大,但是DBA都没,java是全能的,啥都要搞一搞)

    二.分析

      从网上寻找到的资源,可以分成1)业务层面逻辑优化;2)业务层面数据结构优化;3)Sql语句优化。下面实例均来自该项目实际运营中出现的。

      1)业务层面逻辑优化

      案例:司机发送消息接口,接口实现逻辑:后台创建一条司机信息-》推送给司机端-》司机端主动拉取获取消息接口-》内部实现(需优化)-》返回接口信息给司机端。内部实现代码如下:

    /* 
     遍历表yy_common_driver_message,根据条件取的全部的msgId(1) 
     遍历表yy_common_message_status,根据条件取得已发送的msgId;(2) 
     将未发送的msg(1-2),新增到表yy_common_message_status 
     */  
     Map<String,Object> map = new HashMap<String,Object>();  
     map.put("targetUuid", params.get("targetUuid"));  
     List<String> existsList = getMsgUuids(map);  
     AjaxList ajaxList = commonDriverMessageService.getUuids(params);  
     if(ajaxList.isSuccess()){  
         List<String> allList = (List<String>) ajaxList.getData();  
         List<CommonMessageStatusDto> list = new ArrayList<CommonMessageStatusDto>();  
         for(String uuid : allList){  
             if(!existsList.contains(uuid)){  
                 //如果id不包含在已发送,表yy_common_message_status插入新数据  
                 CommonMessageStatusDto dto = new CommonMessageStatusDto();  
                 dto.setUuid(StringUtil.buildUUID());  
                 dto.setMessageUuid(uuid);//msgId  
                 dto.setTargetUuid(params.get("targetUuid").toString());  
                 dto.setStatus(CommonMessageStatusDto.STATUS_UNREAD);//未读  
                 dto.setType(CommonMessageStatusDto.TYPE_SYSTEM);//系统消息  
                 dto.setBusinessType(new Integer(params.get("businessType").toString()));  
                 dto.setTargetType(CommonMessageStatusDto.TARGET_TYPE_DRIVER);//司机  
                 dto.setAppid(params.get("appid").toString());  
                 list.add(dto);  
             }  
         }  
         if(list.size()>0){//如果有。则新增  
             commonMessageStatusMapper.addBatch(list);  
         }  
     }  
    

      初心的设计是为了司机端调用接口的时候,才生产中间表yy_common_message_status的数据,但是由于需求变更,需要主动批量推送给司机,变相是主动触发司机调用接口。这时候,这个设计就不合适了。客户在使用的时候,用车高峰期的时候,主动发送司机消息给所有的司机,司机端收到推送的时候,会主动调用该接口,导致系统查询缓慢。根据讨论结果,内部实现修改为在新增司机消息的时候,新建一个线程,批量插入中间表记录,司机端调用接口的时候,只需要直接执行中间表-消息表的sql语句。优化点:减少数据库交互次数。

      2)业务层面数据结构优化

      软件使用的乘客数不断上升,26W+,一些查询乘客表的sql语句,查询缓慢。Sql语句:SELECT * from yy_passenger where mobile = '15822230119',耗费时间0.66s,查看Mysql执行计划:

    根据查询条件,创建索引,使用索引后,执行SQL查询,耗时0.047s,查看执行计划:

    优化点:合理的使用索引,可以大幅度提升sql查询效率,特别查询的表的数据量大的时候,效果明显。

       3)Sql语句优化

      可以参考链接:http://blog.csdn.net/jie_liang/article/details/77340905,写sql的时候需要注意的,目前就举一例子,营运上遇到的。如下一段mybatis代码

    <select id="getTodayDriverMonitorList" resultType="driverMonitorListBean">  
            select d1.uuid driverUuid,  
                    d1.type,  
                    d1.mobile,  
                    d1.name,  
                    d1.plate_num plateNum,  
                    d1.isWork,  
                    d1.minTime,  
                    d1.maxTime,  
                    d1.timeSum,  
                    count(o.uuid) orderCount,  
                    sum(f.order_fare) fareSum,  
                    sum(f.trip_distance) distanceSum  
            from (  
            select d.uuid,d.type,d.mobile,d.name,d.is_work isWork,c.plate_num,min(l.onWork_time) minTime,max(l.onWork_time) maxTime,sum((TIME_TO_SEC(IFNULL(offWork_time,now())) - TIME_TO_SEC(onWork_time))) timeSum  
            from yy_driver d  
            inner join yy_driver_sign_log l on d.uuid = l.driver_uuid and l.workday = date_format(now(),'%Y-%m-%d')  
            inner join yy_car c on c.uuid = d.car_uuid  
            where 1=1  
            <if test="business != 99 and business !=null">AND d.type = #{business}</if>  
            group by d.uuid,d.mobile,d.name,c.plate_num,d.type,d.is_work  
            ) d1  
    <strong>        left join (SELECT uuid,actual_driver_uuid FROM yy_order where create_time >= curdate() and create_time lt; date_add(curdate(), interval 1 day))o ON o.actual_driver_uuid = d1.uuid  
    </strong>        left join yy_order_fare f on o.uuid = f.order_uuid  
            group by d1.uuid,d1.type,d1.mobile,d1.name,d1.plate_num,d1.minTime,d1.maxTime,d1.timeSum  
        </select>  
    

      

    修改后,执行时间0.52s。

    优化点:SQL语句根据实际情况进行优化。

    三.结尾

      经过这次的SQL管理工作,对SQL优化有一个比较浅的涉及,个人的认为业务逻辑的实现和表结构的设计是顶层设计,而sql语句的优化是在此的基础上。常用的优化方法:索引的创建和分表方式(未涉及,只听说),而索引的创建在合理性,数据库中以空间换时间来实现,SQL语句的查询要避免一些语法导致无法引用索引,而且要根据实际的情况使用好子查询,避免使用全字段查询。

  • 相关阅读:
    【BZOJ2806】【CTSC2012】—熟悉的文章(二分答案+广义后缀自动机+单调队列优化dp)
    2017-2-15
    2017-2-14
    2017-2-13
    CSS居中
    2017-2-10
    微信小程序
    2017-2-9
    2017-2-8
    基础知识再整理: 01
  • 原文地址:https://www.cnblogs.com/knsbyoo/p/9028005.html
Copyright © 2011-2022 走看看