zoukankan      html  css  js  c++  java
  • 关于阿里云 RDS mysql索引优化的一点经验

    2019年9月5日10:02:34

    本地调试

     git https://github.com/barryvdh/laravel-debugbar 

    composer require barryvdh/laravel-debugbar --dev
    APP_DEBUG TRUE

    配置.env

    本地调试很方便,千万不要弄到线上去了,因为这个东西其实很消耗资源的

      公司的项目,因为使用workerman做消息推送,我之前想是做主从,但是想到需要额外花费,而且目前大部分是内部使用,就开始了优化mysql之路

      框架使用的是laravel5.7,基本都要求使用orm,但是框架里面还有有小部分使用的复杂使用的原生的,很多使用联表,注意这里的联表不是join联表,因为性能差异

      

      查询使用的工具都是阿里云提供的工具

      阿里云ApsaraDB诊断报告,SQL洞察分析,

      ApsaraDB诊断报告对检查慢查询还是很有效的,很容易找到问题去优化

    一个demo

    SELECT * FROM `sale_out_storage` WHERE `shop_id` = ? AND `is_delete` = ? AND `storage_status` = ? AND NOT EXISTS ( SELECT * FROM `k3_sale_out_storage_task` WHERE `sale_out_storage`.`id` = `k3_sale_out_storage_task`.`sale_out_storage_id` AND `is_delete` = ? AND `is_cancel` = ? AND `status` IN (?) AND `shop_id` = ? ) AND EXISTS ( SELECT * FROM `sale_order` WHERE `sale_out_storage`.`sale_order_id` = `sale_order`.`id` AND `order_status` != ? ) AND `storage_date` > ? 建议 1. 返回记录数 语句最大返回记录数为55。

    2. 行扫描 行扫描与行返回之比为178673。

    3. 索引 该语句没有使用聚合函数和模糊查询,行扫描与行返回之比很高。创建合理索引会带 来很大的优化空间

    SQL语句
    数据库
    线程ID
    用户
    客户端IP
    操作
    状态
    耗时(ms)
    执行时间
    更新行数
    扫描行数
    select `id`, `user_id`, `admin_id`, `type`, `type_flag`, `content`, `operation_user_id`, `operation_admin_id`, `is_read`, `shop_id`, `message_tag`, `message_type`, `create_time` from `operation_log` where `admin_id` = 14 and `operation_admin_id` != 14 and `is_read` = 1 and `message_type` in (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19) and `create_time` >= '2019-06-01 00:00:00' order by `id` desc limit 10 offset 0
    v2
    60130
    youse
    172.18.112.8
    SELECT
    成功
    0.25
    2019年9月6日 10:57:50
    0
    13
    select count(*) as aggregate from `operation_log` where `user_id` = ? and `is_read` = ?
    v2
    24
    youse
    172.18.112.8
    SELECT
    成功
    0.04
    2019年9月6日 10:57:50
    0
    0
    select * from `sale_voucher` where `is_delete` = 10 and `shop_id` = 1 and `admin_id` = 14 and `status` = 30 and `create_time` >= '2019-01-01' order by `id` desc limit 5 offset 0
    v2
    60130
    youse
    172.18.112.8
    SELECT
    成功
    0.48
    2019年9月6日 10:57:50
    0
    289
    select `id`, `user_id`, `admin_id`, `type`, `type_flag`, `content`, `operation_user_id`, `operation_admin_id`, `is_read`, `shop_id`, `message_tag`, `message_type`, `create_time` from `operation_log` where `admin_id` = ? and `operation_admin_id` != ? and `is_read` = ? and `message_type` in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) and `create_time` >= ? order by `id` desc limit 10 offset 0
    v2
    60130
    youse
    172.18.112.8
    SELECT
    成功
    0.12
    2019年9月6日 10:57:50
    0
    0
     
                       
    select * from `admin_permission` where `is_delete` = 10 and `id` in (1, 3, 69, 148,, 439, 440, 428, 429, 430, 431, 432, 433, 444, 115, 244, 245, 246, 247, 248, 249, 239, 389, 390, 129, 331, 332, 333, 334, 391, 392, 393, 394, 395, 149)
    v2
    60130
    youse
    172.18.112.8
    SELECT
    成功
    1.04
    2019年9月6日 10:57:50
    0
    527

    我发现的最大的问题有以下几点:

      1,where in的性能其实很差,经常需要大范围扫描,减少in的范围,或者使用exists代替

      2,使用时间范围查询的时候一定要加上索引,不然效率很差,大范围扫描行数

      3,索引不能添加过多,过多也会导致性能下降,比如log日志表,提供给多方查询的时候,添加过多,mysql内部多个索引进行查询的时候,会增加计算量,大大消耗cpu

      4,如果有多个索引比如订单表,请注意一定优先最左原则,最大化利用索引,强调代码规范

      5,join 会大大增加内存消耗,即使在符合大表连小表的原则

      6,适当添加索引,特别是在laravel with联表的时候

    $parent_sale_order_info = SaleOrder::where('shop_id', $shop_id)->where('is_delete', 10)
                    ->with([
                        'sale_order' => function ($query) {
                            $query->where('is_delete', 10)->with([
                                'sale_out_storage' => function ($query) {
                                    $query->where('is_delete', 10)->where('storage_status', 20)->with([
                                        'sale_out_storage_sku' => function ($query) {
                                            $query->where('is_delete', 10);
                                        }
                                    ]);
                                },
                                'sale_pay' => function ($query) {
                                    $query->where('is_delete', 10);
                                }
                            ]);
                        },
                        'sale_settle' => function ($query) {
                            $query->where('is_delete', 10)->with([
                                'sale_settle_sku' => function ($query) {
                                    $query->where('is_delete', 10);
                                }
                            ]);
                        },
                        'sale_pay_record' => function ($query) {
                            $query->where('is_delete', 10)->where('status', 20);
                        }
                    ])
                    ->where('id', $parent_order_id)
                    ->first();

    优化完的结果

    有日常80%-95%,优化完之后30%上下,阿里云的rds mysql 5.7,2核4g

    补充一点,核心的解决办法就是找到出问题点在哪,我这个场景就是因为推送大大增加数据查询消耗,导致mysql扫描行大大增加

    解决思路如下:了解业务的繁忙点,找到频繁的核心表,优先尝试,优化索引,这样的就不需要修改很多代码,如果发现只优化索引不能解决,坚决修改代码,并指导开发人员是为什么需要这样写

    更改书写习惯和理念,这样才能根本解决问题,不然只是临时救火。

    一点参考的文章

    https://www.cnblogs.com/ManyQian/p/9076247.html#_label2

    https://www.cnblogs.com/ManyQian/p/9038063.html

    https://www.cnblogs.com/ManyQian/p/9026606.html

    https://www.cnblogs.com/zjxiang/p/9160810.html

  • 相关阅读:
    stata如何建立交互项
    PSM的stata实现
    Stata结果输出:outreg2命令详解
    stata固定效应
    【C++/Qt】cmake生成可执行文件流程(Windows/Linux)
    【数学相关】概率论手写笔记
    【搜索】dfs&bfs
    【C/C++】对拍教程
    【MySQL】MySQL基础操作(下)
    【Linux】ubuntu初始配置
  • 原文地址:https://www.cnblogs.com/zx-admin/p/11465672.html
Copyright © 2011-2022 走看看