最近在生产客服平台,运营岗老师反馈,一个2w人的企业,在信息详情查询时,加载时间过长,越70s左右出结果,需要后台优化下sql。
首先展示一下原sql
select distinct pma.member_apply_id, tm.mobile_num, tpp.product, tpp.plan_id, tpp.plan_name, pma.org_name, vtor.role_id, tp.person_id, tp.real_name, tp.certi_code, tp.birthday, pma.start_work_date, pma.rank, pma.retire_age, pma.month_base, ext.self_define_11, ext.now_month_salary, pma.employee_date, pma.eff_date, pma.employee_no, pma.member_sts_id, pma.account_state_id, tp.certi_type, tp.gender, decode(tp.gender, 'm', '男' , 'f', '女') sexname, mt.member_sts_name memberstatename, amt.account_sate_desc accountstatename, ct.certi_type_name certitypename, pma.email from tms_plan_member_apply pma, tms_person tp, tms_mobile_number_screen tm, v_tms_org_role vtor, tms_product_plan tpp, tms_certi_type_tbl ct, tms_member_sts_tbl mt, tms_member_account_sate amt, tms_plan_member_collect_ext ext, (select max(pma2.member_apply_id) member_apply_id from tms_plan_member_apply pma2, tms_busi_apply tba2 where tba2.flow_sts_id = 9999 and exists (select 1 from v_tms_org_role t where t.role_type = '13' and t.org_name = pma2.org_name start with t.role_id = '46000' connect by prior t.org_id = t.parent_org) and tba2.apply_id = pma2.busi_apply_id and tba2.plan_id = '39076' group by pma2.person_id) t1 where ((tm.screen_id = (select max(mm.screen_id) from tms_mobile_number_screen mm where mm.person_id = tm.person_id)) or tm.screen_id is null) and ext.apply_id(+) = pma.busi_apply_id and ext.person_id(+) = pma.person_id and ct.certi_type_id(+) = tp.certi_type and pma.person_id = tp.person_id and tm.person_id(+) = pma.person_id and mt.member_sts_id(+) = pma.member_sts_id and amt.account_sate_id(+) = pma.account_state_id and vtor.org_name = pma.org_name and vtor.role_type = 13 and t1.member_apply_id = pma.member_apply_id and tpp.plan_id = '39076' order by tp.real_name遇到这种sql,我们第一步是要将无用的查询和码表去掉,来简化这种较长的sql,如上面所展示,去除tms_mobile_number_screen 、tms_certi_type_tbl、tms_member_sts_tbl、tms_member_account_sate表关联。
之后发现,当去掉tms_plan_member_collect_ext这个表的关联条件后,查询的速度就特别快,sql中,使用该表的关联条件为:
ext.apply_id(+) = pma.busi_apply_id
and ext.person_id(+) = pma.person_id
oracle中的(+)是一种特殊的用法,(+)表示外连接,并且总是放在非主表的一方。例如左外连接:
select a.a,b.a from a left join b on a.b=b.b;
等价于
select a.a,b.a from a,b where a.b = b.b (+);
再举个例子,这次是右外连接:
select a.a,b.a from a right join b on a.b=b.b;
等价于
select a.a,b.a from a,b where a.b (+) = b.b;
观察了一下ext表的结构,发现使用了联合索引,联合索引就是apply_id和person_id两个字段,这时候第一反应是索引是否生效,看了一下执行计划,确实走了索引,这里普及一下索引是否生效的例子:
索引:idx(b,c)
select id where b = xx;
select id where c = xx;
上面的两句sql会走b,c的联合索引吗?
答案是第一条会走,第二条不会。
那多个字段的联合索引,使用部分字段会走索引吗?例如 idx(a,b,c) select id where b = xx and c = xx;
答案是不会,其实不管是多少个字段的联合索引,不管查询顺序,不管查询用到了几个字段,只要没有使用联合索引的第一个字段,则不会走联合索引。
在数据量很大的表中,联合索引要比单个索引要慢,因为要比对两次,接着看表索引,发现该表有一个主键是索引,果断采用主键索引,因为唯一性高,使用主键索引后,速度立刻由70s下降到0.5s左右。
芯片制造的6个关键步骤
三相六线电机接线电路图
过去一年NB-IoT成果丰硕,下一价值拐点将至
光耦合器IC的类型及规格
苹果供应链加速迁离中国?
Oracle长耗时SQL优化案例
数字温度传感器选择 你需要考虑什么?
不倒翁的秘密 平衡车传感器监测原理
台积电新竹总部12 B厂意外发生火警事件
磷酸铁锂电池蔚然成风,动力电池技术之争重现江湖
LOGO!的基本指令是什么
digilentPmodCMPS:三轴数字罗盘简介
智能油烟监测系统,助力解决餐饮大气污染
实用的高清全景摄像机可取代传统的监控设备
氙灯老化试验机采用风冷好还是水冷好
戴尔(DELL)笔记本电脑电池型号有哪些?
来自语障人士的语音数据集合
三星已找到第二家3nm芯片客户 产能开始供不应求
华为智能光伏已助力客户累计绿色发电4702亿度
PS4虚拟眼镜高清图赏