MySQL调优实践篇

MySQL调优实践篇

记一次实习MySQL调优

业务需求:热门帖子展示

  • 统计该帖子在某段时间内的评论量、浏览量,按评论量、浏览量、帖子创建时间降序排序

三张表:app_invitation帖子表、app_invitation_comment帖子评论表、app_invitation_look帖子浏览记录表

调优步骤

调优背景:之前离职员工开发好的部分,测试时数据量少,未发现响应速度太慢问题,数据量增加,响应速度太慢,需进行优化

  1. 先查看代码是否需要优化 :

    • 不需要对所有查询出来的数据都进行处理,对需要显示的部分进行处理即可
  2. sql语句的编写

    原sql语句编写冗余,既联表又子查询都是为得到同一信息点

    <select id="moreHotList" resultType="AppInvitation" >
            SELECT count(b.id) count,a.look,
        	(SELECT IFNULL(sum(look),0) from
            app_invitation_look where create_time BETWEEN #{start} and #{end} and invitation_id = a.id) look2,
        	a.id, a.type,a.tile_category tileCategory, a.tile_specification tileSpecification,a.description, a.uid, a.phone, a.city, a.hot, a.top,  a.longitude, a.latitude, a.enterprise,a.machine_trial machineTrial, a.state, a.dev, a.create_time createTime, a.update_time updateTime FROM
            app_invitation a LEFT JOIN app_invitation_comment b ON a.id = b.invitation_id LEFT JOIN app_invitation_look c on a.id = c.invitation_id
        	where a.dev = 1 AND a.state = 1 AND a.machine_trial = 1
            GROUP BY a.id 
            <if test="last != null ">
                and a.update_time &lt;= #{last}
            </if>
            ORDER BY count desc,look2 desc,a.create_time desc
        </select>
    
    • 通过explain查看执行计划,两个表的type是all

      • 分别为app_invitation_comment帖子评论表、app_invitation_look帖子浏览记录表建立invitation_id的索引
      • 结果:子查询和联表部分的type 为ref
    • 帖子表查询的extra列 using temporary、using filesort

      • using temporary,通过网上检索发现可能是由于innodb_buffer_pool_size设置过小,而建立了临时表,通过show variable like “%innodb_buffer_pool_size%”发现现有设置为128M,修改为256M

      • using filesort在内存中排序,排序字段是利用联表/子查询统计出来的字段,不好建立索引:

        (注:以下执行时间是由于笔者是在数据量小的数据库执行只用于展示)

        1. 通过set profiling = 1;执行sql语句,再show profiles 可以查看具体执行时间

          [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5OAd23kt-1661079391604)(C:\Users\蔡晓娜\AppData\Roaming\Typora\typora-user-images\image-20220821183759188.png)]

        2. 可以通过show profile for query query_id,query_id,即对应这Query_ID这一列具体的数值,

          show profile for query 2;可以查看每个步骤具体花费时间

          [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xmQZ6pWG-1661079391606)(C:\Users\蔡晓娜\AppData\Roaming\Typora\typora-user-images\image-20220821184058085.png)]

        3. 发现排序较花费时间,排序字段是利用子查询出来的字段,不好建立索引;using filesort在内存中排序,其中有两种排序方式,决定排序方式的sort_buffer_size 参数设置,默认是1MB,为使用单路排序,选择增大参数值

        4. 其中一个排序字段创建时间,与自增id是正相关,将create_time改为id

        5. 结合业务需求,数据库会包含逻辑删除的帖子,即实际上并不是所有帖子都要检索,原本是在联表之后通过where语句筛选,笔者改为在join之前先对帖子进行筛选

最终版本:

<select id="moreHotList" resultType="AppInvitation" >
    SELECT count(b.id) comment,a.look,
    (SELECT IFNULL(sum(look),0) from app_invitation_look where create_time BETWEEN #{start} and #{end} and invitation_id = a.id) look2,
    a.id, a.type,a.tile_category tileCategory, a.tile_specification tileSpecification,
    a.description, a.uid, a.phone, a.city, a.hot, a.top, a.longitude, a.latitude, a.enterprise,
    a.machine_trial machineTrial, a.state, a.dev, a.create_time createTime, a.update_time updateTime
    FROM (SELECT * FROM app_invitation where dev = 1 AND state = 1 AND machine_trial = 1
    <if test="last != null ">
        and update_time &lt;= #{last}
    </if>
    ) a
    LEFT JOIN app_invitation_comment  b
    on a.id = b.invitation_id and b.create_time BETWEEN #{start} and #{end} and b.hidden = 2 and b.machine_trial = 1 and b.dev = 2
    GROUP BY a.id
    ORDER BY comment desc,look2 desc,a.id desc
</select>
and b.dev = 2
    GROUP BY a.id
    ORDER BY comment desc,look2 desc,a.id desc
</select>

猜你喜欢

转载自blog.csdn.net/weixin_47407737/article/details/126454080