慢sql治理经典案例分享
简介:菜鸟供应链金融慢sql治理已经有一段时间,自己负责的应用持续很长时间没有慢sql告警,现阶段在推进组内其他成员治理应用慢sql。这里把治理过程中的一些实践拿出来分享下。
作者 | 如期
来源 | 阿里技术公众号
菜鸟供应链金融慢sql治理已经有一段时间,自己负责的应用持续很长时间没有慢sql告警,现阶段在推进组内其他成员治理应用慢sql。这里把治理过程中的一些实践拿出来分享下。
一 全表扫描
1 案例
SELECT count(*) AS tmp_count FROM (
SELECT * FROM `XXX_rules` WHERE 1 = 1 ORDER BY gmt_create DESC ) a
2 溯源
在分页查询治理的文章里已经介绍过我们系统旧的分页查询逻辑,上面的查询sql明显就是分页查询获取总记录数,通过XXX_rules表的分页查询接口溯源,找到发起调用的页面是我们小二后台的一个操作商家准入的页面,页面打开后直接调用分页查询接口,除了分页参数,不传入其他任何查询参数,导致扫描全表。
3 分析
灵魂拷问:为什么要扫描全表?全表数据展示到页面,花里胡哨的数据有用吗?
调研:和经常使用这个页面的运营聊后了解到,打开页面查询出的全表数据对运营是没有用的,他们根本不看这些数据。运营的操作习惯是拿到商家id,在页面查询框中输入商家id,查到商家数据后进行操作。
4 解决方案
由此优化方案就很明朗了:打开页面时不直接查询全量数据,等运营输入商家id后,将商家id作为参数进行查询。XXX_rules表中,商家id这一常用查询条件设置为索引,再结合分页查询优化,全表扫描慢sql得以解决。
优化后的小二后台页面如下:
打开页面时未查询任何数据,查询条件商家账户为必填项。
优化后的sql为:
SELECT count(*) AS tmp_count FROM (
SELECT * FROM `xxx_rules` WHERE 1 = 1 AND `rule_value` = '2928597xxx' ) a
执行EXPLAIN得到结果如下:
可以看到命中了索引,扫描行数为3,查询速度明显提高。
5 思考
扫描全表治理简单来说就是加入查询条件,命中索引,去除全表扫描查询,虽然有些粗暴,但并不是没有道理。实际业务场景中,很少有要扫描全表获取全部数据的情况,限制调用上游必须传入查询条件,且该查询条件能命中索引,能很大程度上避免慢sql。
另外,再引申下,XXX_rules初始的用意是准入表,记录金融货主维度的准入情况,最多也就几千条数据,但是很多同事将这张表理解为规则表,写入很多业务相关规则,导致这个表膨胀到一百多万条数据,表不clean了。这就涉及到数据表的设计使用,明确表的使用规范,不乱写入数据,能给后期维护带来很大的便利。
二 索引混乱
1 示例
2 分析
除了时间、操作人字段,XXX_rules表就rule_name、rule_value、status、product_code四个字段,表的索引对这四个字段做各种排列组合。存在如下问题:
1、rule_name离散度不高,放在索引首位不合适;
2、前三个索引重合度很高;
显然是对索引的命中规则不够了解。XXX_rules表很多业务有定时任务对其写入删除,索引多、混乱,对性能有很大的影响。
高性能的索引有哪些,再来回顾下:
1、独立的列:索引列不能是表达式的一部分;
2、选择区分度高的列作为索引;
3、选择合适的索引列顺序:将选择性高的索引列放在最前列;
4、覆盖索引:查询的列均在索引中,不需要回查聚簇索引;
5、使用索引扫描来做排序;
6、在遵守最左前缀的原则下,尽量扩展索引,而不是创建索引。
但凡记得第3和6规则,也不至于把索引建成这样。
3 治理
对索引进行整合如下:
系统中有很多任务拉取整个产品下的准入记录,然后进行处理,所以将区分度较高的product_code放在索引首位,然后添加rule_name、status字段到索引里,进一步过滤数据,减少扫描行数,避免慢sql。针对常用的rule_value查询条件,可以命中UK,因此不用单独建立索引。
三 非必要排序
1 问题描述
很多业务逻辑中,需要拉取满足某个条件的记录列表,查询的sql语句带有order by,记录比较多的情况,排序代价往往很大,但是查询出来的记录是否有序对业务逻辑没有影响,比如分页治理里讨论的count语句,只需要统计条数,order by对条数没有影响,再比如查出记录列表后,不依赖记录的顺序遍历列表处理数据,这时候order by多此一举。
2 解决方案
查询sql无limit语句,且业务处理逻辑不依赖于order by后列表记录的顺序,则去除查询sql中的order by语句。
四 粗粒度查询
1 问题描述
业务中有很多定时任务,扫描某个表中某个产品下所有数据,对数据进行处理,比如:
SELECT * FROM XXX_rules
WHERE rule_name = 'apf_distributors'
AND status = '00'
AND product_code = 'ADVANCE'
三个查询条件都是区分度不高的列,查出的数据有27W条,加索引意义也不大。
2 分析
实际业务量没那么大,顶多几千条数据,表里的数据是从上游同步过来的,最好的办法是让上游精简数据,但是由于业务太久远,找上游的人维护难度太大,因此只能想其他的办法。
这个定时任务目的是拉出XXX_rules表的某些产品下的数据,和另一张表数据对比,更新有差异的数据。每天凌晨处理,对时效性没有很高的要求,因此,能不能转移任务处理的地方,不在本应用机器上实时处理那么多条数据?
3 解决方案
数据是离线任务odps同步过来的,首先想到的就是dataWork数据处理平台。
建立数据对比任务,将定时任务做的数据对比逻辑放到dataWork上用sql实现,每天差异数据最多几百条,且结果集含有区分度很高的列,将差异数据写入odps表,再将数据回流到idb。
新建定时任务,通过回流回来的差异数据中区分度高的列作为查询条件查询XXX_rules,更新XXX_rules,解决了慢sql问题。
这个方法的前提是对数据实效性要求不高,且离线产出的结果集很小。
五 OR导致索引失效
1 案例
SELECT count(*)
FROM XXX_level_report
WHERE 1 = 1
AND EXISTS (
SELECT 1
FROM XXX_white_list t
WHERE (t.biz_id = customer_id
OR customer_id LIKE CONCAT(t.biz_id, '@%'))
AND t.status = 1
AND (t.start_time <= CURRENT_TIME
OR t.start_time IS NULL)
AND (t.end_time >= CURRENT_TIME
OR t.end_time IS NULL)
AND t.biz_type = 'GOODS_CONTROL_BLACKLIST'
)
2 分析
explain上述查询语句,得到结果如下:
XXX_white_list表有将biz_id作为索引,这里查询XXX_white_list表有传入biz_id作为查询条件,为啥explain结果里type为ALL,即扫描全表?索引失效了?索引失效有哪些情况?
索引失效场景
1、OR查询左右有未命中索引的;
2、复合索引不满足最左匹配原则;
3、Like以%开头;
4、需要类型转换;
5、where中索引列有运算;
6、where中索引列使用了函数;
7、如果mysql觉得全表扫描更快时(数据少时)
上述查询语句第8行,customer_id为XXX_level_report表字段,未命中XXX_white_list表索引,导致索引失效。
3 解决方案
这个语句用condition、枚举、join花里胡哨的代码拼接起来的,改起来好麻烦,而且看起来“OR customer_id LIKE CONCAT(t.biz_id, '@%')”这句不能直接删掉。最后重构了该部分的查询语句,去除or查询,解决了慢sql。
本文为阿里云原创内容,未经允许不得转载。
慢sql治理经典案例分享的更多相关文章
- SQL优化 · 经典案例 · 索引篇
Introduction 在这些年的工作之中,由于SQL问题导致的数据库故障层出不穷,下面将过去六年工作中遇到的SQL问题总结归类,还原问题原貌,给出分析问题思路和解决问题的方法,帮助用户在使用数据库 ...
- Java多线程经典案例分享
汇总 案例一 案例二 案例三 案例四 案例五 案例六 案例七 案例一 实现一个容器,提供两个方法,add(),count() 写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数,当个数 ...
- SQL Server 经典案例
1.先进先出 例1 WITH [ta] ([商品编号], [批次号], [库存数量]) AS ( UNION ALL UNION ALL UNION ALL ),[tb] ([商品编号], [订货数量 ...
- Oracle学习总结(5)—— SQL语句经典案例
--0.所有员工信息 SELECT * FROM emp --1.选择部门30的所有员工 SELECT * FROM emp WHERE deptno=20 --2.列出所有办事员(CLERK)的姓名 ...
- MySQL进阶8 分页查询(limit) - 【SQL查询语法执行顺序及大致结构】- 子查询的3个经典案例
#进阶8 分页查询 /* 应用场景: 当要显示的数据,一页显示不全,需要分页提交sql请求 语法: select 查询列表 #7 from 表1 #执行顺序:#1 [join type join 表2 ...
- SQL server经典电子书、工具和视频教程汇总
SQL server经典电子书.工具和视频教程汇总 SQL server经典电子书.工具和视频教程汇总 SQL Server是高校计算机专业的一门必修课程,同时众多企业采用SQL Server作为数据 ...
- 阿里云资深DBA专家罗龙九:云数据库十大经典案例分析【转载】
阿里云资深DBA专家罗龙九:云数据库十大经典案例分析 2016-07-21 06:33 本文已获阿里云授权发布,转载具体要求见文末 摘要:本文根据阿里云资深DBA专家罗龙九在首届阿里巴巴在线峰会的&l ...
- 100个Linux Shell脚本经典案例(附PDF)
转载自:https://mp.weixin.qq.com/s/tCKAM67_7K7q2vJthaIsDQ 原文链接:https://wenku.baidu.com/view/4f089430a116 ...
- Linux运维之道(大量经典案例、问题分析,运维案头书,红帽推荐)
Linux运维之道(大量经典案例.问题分析,运维案头书,红帽推荐) 丁明一 编 ISBN 978-7-121-21877-4 2014年1月出版 定价:69.00元 448页 16开 编辑推荐 1 ...
- 经典案例:那些让人赞不绝口的创新 HTML5 网站
在过去的10年里,网页设计师使用 Flash.JavaScript 或其他复杂的软件和技术来创建网站.但现在你可以前所未有的快速.轻松地设计或创造互动的.有趣好看的网站.如何创建?答案是 HTML5 ...
随机推荐
- 如何在forEach内使用异步调用 async/await
翻自: How to use async and await in a forEach JS loop? https://learn.coderslang.com/0144-how-to-use-as ...
- 在Blazor中使用Chart.js快速创建图表
前言 BlazorChartjs是一个在Blazor中使用Chart.js的库(支持Blazor WebAssembly和Blazor Server两种模式),它提供了简单易用的组件来帮助开发者快速集 ...
- openlayers操作分享:如何从容的在vue中食用openlayers6
这篇文章,分享下我对openlayers的一些经验和理解,会夹杂大量搜索出来得文档,是我正式使用时可以实现的,废话不多说,我们从下载开始 一,openlayers安装且初始化地图 创建vue项目就省略 ...
- 记录-因为写不出拖拽移动效果,我恶补了一下Dom中的各种距离
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 背景 最近在项目中要实现一个拖拽头像的移动效果,一直对JS Dom拖拽这一块不太熟悉,甚至在网上找一个示例,都看得云里雾里的,发现遇到最大 ...
- [Git]关联远程库的两种方法及配置
[版权声明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://www.cnblogs.com/cnb-yuchen/p/18000705 出自[进步*于辰的博客] 参考笔记三,P ...
- linux安装jdk压缩包版
1.下载压缩包可以选择国内大厂的jdk镜像网站下载速度很快, 比如华为的:https://repo.huaweicloud.com/java/jdk/ 2.查看Linux系统是否有自带的jdk: 输入 ...
- 英语文档阅读学习系列之ZYNQ-7000 All Programmable SOC Packaging and Pinout
UG865-Zynq-7000-pkg-pinout 1.Table 一个overview和其他部分的构成一个整体. 2.overview This section describes the pin ...
- idea创建一个干净的SpringMVC项目
一.创建普通的maven项目 二.右键添加web支持 三.pom.xml配置maven环境 1 <!--导入依赖--> 2 <dependencies> 3 <depen ...
- ET介绍——事件机制EventSystem
事件机制EventSystem ECS最重要的特性一是数据跟逻辑分离,二是数据驱动逻辑.什么是数据驱动逻辑呢?不太好理解,我们举个例子 一个moba游戏,英雄都有血条,血条会在人物头上显示,也会在左上 ...
- 前端问题整理 Vite+Vue3+Ts 创建项目及配置 持续更新
前端问题整理 持续更新 目录 前端问题整理 持续更新 前端 Vue 篇 @项目配置 1.node 版本过高问题 安装nvm 管理node版本 2.镜像证书无效问题 3.npm 版本问题 4.npm i ...