高响应延迟优化实战:

前言:

今天帮同事处理客户现场一个超高响应延迟的接口:由于客户数据达到几十W条,此接口客户环境居然跑了22S,首先通过走查代码发现以下几个严重问题:
1.一个严重的循环RPC调用跑了10s,改为批量以后耗时50ms,此时这个接口响应延迟大概12s左右;
2.循环逻辑,此同事将结果集数据list1的主键取出来后,又通过主键从所有数据中取出数据list2,此段代码完全无意义,跑了5s,删除后,此时这个接口响应延迟大概7s左右;
3.然后定位到一个sql跑了5s左右,加索引后1s,此时这个接口响应延迟大概3s左右;
4.然后通过异步等操作,最终接口速度2s。

下面主要记录下通过加索引的方式优化此接口的部分;其他方式后续会逐步更新:

最有效的调优是添加索引,添加索引可以避免全表扫描;且我们应避免添加索引后索引失效的操作;
在这里插入图片描述

应该添加索引的4地方:
Where后面经常出现的字段
Order by后排序的关键字
Group by后分组的的关键字
Join on 后的关键字

分类:

PRIMARY, INDEX, UNIQUE 这3种是一类

PRIMARY 主键。 就是 唯一 且 不能为空。

INDEX 索引,普通的

UNIQUE 唯一索引。 不允许有重复。

FULLTEXT 是全文索引,用于在一篇文章中,检索文本信息的。
MYSQL的索引类型:PRIMARY, INDEX,UNIQUE,FULLTEXT,SPAIAL 有什么区别?各适用于什么场合?

举个例子来说,比如你在为某商场做一个会员卡的系统。
这个系统有一个会员表
有下列字段:
会员编号 INT
会员姓名 VARCHAR(10)
会员身份证号码 VARCHAR(18)
会员电话 VARCHAR(10)
会员住址 VARCHAR(50)
会员备注信息 TEXT

那么这个 会员编号,作为主键,使用 PRIMARY
会员姓名 如果要建索引的话,那么就是普通的 INDEX
会员身份证号码 如果要建索引的话,那么可以选择 UNIQUE (唯一的,不允许重复)
会员备注信息 , 如果需要建索引的话,可以选择 FULLTEXT,全文搜索。

不过 FULLTEXT 用于搜索很长一篇文章的时候,效果最好。
用在比较短的文本,如果就一两行字的,普通的 INDEX 也可以。

Mysql 添加索引:

mysql两种方式直接创建索引、修改表创建索引,oracle一种只能直接创建索引:
0.mysql直接创建索引:
create index IX_PLANDETAIL_PLANINFOID on PL_PLAN_DETAIL(PL_PLAN_INFO_ID);
1.添加主键
ALTER TABLE tbl_name ADD PRIMARY KEY (col_list);
// 该语句添加一个主键,这意味着索引值必须是唯一的,且不能为NULL。
2.添加唯一索引
ALTER TABLE tbl_name ADD UNIQUE index_name (col_list);
// 这条语句创建索引的值必须是唯一的。
3.添加普通索引
ALTER TABLE tbl_name ADD INDEX index_name (col_list);
// 添加普通索引,索引值可出现多次。
4.添加全文索引
ALTER TABLE tbl_name ADD FULLTEXT index_name (col_list);
// 该语句指定了索引为 FULLTEXT ,用于全文索引。
PS: 附赠删除索引的语法:
DROP INDEX index_name ON tbl_name;
// 或者
ALTER TABLE tbl_name DROP INDEX index_name;
ALTER TABLE tbl_name DROP PRIMARY KEY;

oracle 添加索引:

create index t_student_birthday on t_student(birthday);

实际测试:

同事sql:

        select * from (
        select DISTINCT PI.ORDER_NO,
        PI.TASK_NAME,
        CASE PI.YN_MILESTONE WHEN '0' THEN '是' WHEN '1' THEN '否' END AS YN_MILESTONE,
        (SELECT CONCAT(CONCAT(ORDER_NO,' '),TASK_NAME) FROM PL_PLAN_INFO WHERE ORDER_NO = PI.TASK_BEFORE_ID AND
        PL_PROJECT_MAIN_ID=PM.PL_PROJECT_MAIN_ID) AS
        TASK_BEFORE_NAME,
        CONCAT(CONCAT(PM.PL_PROJECT_NO,' '),PM.PL_PROJECT_NAME) AS PL_PROJECT_NO,
        PM.PL_PROJECT_NO as PL_NO,
        R.PL_TASK_REPORT_RUM_ID,
        PD.PL_PLAN_DEPT_ID,
        D.DEPT_NAME,
        PD.BEGIN_TIME,
        PD.OVER_TIME,
        PD.TASK_STATUS,
        PD.PER_INCHARGE_NAME,
        PD.PER_INCHARGE_ID,
        PD.PER_INCHARGE_DEPT_NAME,
        PD.INPUT_FILE,
        PD.OUTPUT_FILE,
        PD.CHECK_STANDARD,
        PD.RESULT_NOTE,
        PD.PL_PLAN_DETAIL_ID,
        PM.CHANGE_STATUS,
        PM.PROJECT_PHASE,
        PI.PL_PROJECT_MAIN_ID,
        PD.YN_SIGN,
        PD.YN_PROCESS_CHK,
        M.PRO_MEMBER_ID,
        M.PRO_MEMBER_ORG_ID,
        WR.NODE_USER_ID,
        NVL(WR.FLOW_STATUS,1) FLOW_STATUS,
        case WR.FLOW_STATUS
        when '2' then '进行中'
        when '3' then '通过'
        when '4' then '暂停'
        when '5' then '中止'
        when '6' then '拿回'
        when '7' then '批回'
        else '草稿' end as flowStatusDesc,
        concat((case TASK_STATUS
        when '0' then '进行中'
        when '1' then '已完成'
        when '2' then '超期未完成'
        when '3' then '超期完成'
        when '4' then '质量不合格'
        when '5' then '质量检查中' end),
        (case PM.CHANGE_STATUS
        when '2' then '(一级计划变更中)'
        when '3' then '(二级计划变更中)'
        when '4' then '(三级计划变更中)'
        when '5' then '(项目暂停中)'
        when '6' then '(项目中止)'
        ELSE '' end)
        ) as taskStatusName
        from PL_PLAN_DETAIL PD
        LEFT JOIN PL_PLAN_DEPT D ON PD.PL_PLAN_DEPT_ID = D.PL_PLAN_DEPT_ID
        LEFT JOIN PL_PLAN_INFO PI ON PI.PL_PLAN_INFO_ID = PD.PL_PLAN_INFO_ID
        LEFT JOIN PL_PROJECT_MAIN PM ON PI.PL_PROJECT_MAIN_ID = PM.PL_PROJECT_MAIN_ID
        LEFT JOIN PL_PRO_MEMBER M ON PM.PL_PROJECT_MAIN_ID=M.PL_PROJECT_MAIN_ID AND M.PRO_ROLE = '0'
        LEFT JOIN (select * from(select
        PL_TASK_REPORT_RUM_ID,PL_PLAN_DETAIL_ID,PL_PROJECT_MAIN_ID,ORDER_NO,DEPT_NAME,row_number() over (partition by
        PL_PROJECT_MAIN_ID,ORDER_NO,DEPT_NAME order by CREATION_DATE desc) rn from PL_TASK_REPORT_RUM)where rn=1)R on
        (R.PL_PROJECT_MAIN_ID=PI.PL_PROJECT_MAIN_ID and R.ORDER_NO=PI.ORDER_NO and R.DEPT_NAME=D.DEPT_NAME)
        LEFT JOIN WF_FLOW_CLIENT_RUN WR ON WR.BUSINESS_KEY_=R.PL_TASK_REPORT_RUM_ID
        where
				((PM.PROJECT_PHASE='7' OR PM.PROJECT_PHASE='8') OR (PM.CHANGE_STATUS!='1')) and (PM.PL_PROJECT_ISPASS='1')
        AND PI.TASK_CLASS !='1'
        AND PD.PER_INCHARGE_ID IS NOT NULL
        )

        order by PL_PROJECT_NO asc,ORDER_NO asc

添加索引:

create index IX_MEMBER_PLPROJECTMAINID on PL_PRO_MEMBER(PL_PROJECT_MAIN_ID);

create index IX_FLOWRUN_BUSINESSKEY_ on WF_FLOW_CLIENT_RUN(BUSINESS_KEY_);


create index IX_PLANINFO_ORDERNO on PL_PLAN_INFO(ORDER_NO);

create index IX_PLANINFO_PLPROJECTMAINID on PL_PLAN_INFO(PL_PROJECT_MAIN_ID);


create index IX_PLANDETAIL_PLANINFOID on PL_PLAN_DETAIL(PL_PLAN_INFO_ID);

create index IX_PLANDETAIL_PLANDEPTID on PL_PLAN_DETAIL(PL_PLAN_DEPT_ID);

在开发库中测试(约2300条数据):
不加索引时:大约耗时0.23S

在这里插入图片描述

添加索引后:大约耗时0.1S
在这里插入图片描述

可见查询效率提升很多!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值