对SQL 优化,提升性能!
对SQL 进行优化能够有效提高SQL 语句的执行效率,降低系统资源开销,是开发者提高后端系统处理能力的首选方案。
新产品上线后,随着运营推广活动的开始,业务进入快速增长期,数据库作为后端系统唯一或者主要持久化组件,无论是存储的数据量还是事务请求次数都呈现指数级增长,数据库的处理能力逐渐成为整个系统的性能瓶颈。
提高物理规格配置虽然可以起到一定程度的缓解作用,但毕竟只是治标不治本,同时也会带来高额的硬件成本。分布式数据库虽然听起来高大上,但是系统改造成本以及开发运维成本又让一般的中小型团队望而却步。
SQL 优化能够有效提高SQL 语句的执行效率,降低系统资源开销,是开发者提高后端系统处理能力的首选方案。
SQL 优化是指通过采集SQL 执行的多项关键指标,分析SQL 的执行过程,根据数据库中表数据以及索引,对SQL 语句进行改写或者调整索引,最终达到SQL 语句按照最佳执行计划执行的目的。
接下来,我们就来介绍下SQL 优化的一般步骤。
第一步:收集SQL 语句
SQL 优化的起点是用户访问数据库的SQL 语句,尤其是问题SQL 语句。在数据库中,主要是访问超时的SQL 语句。
MySQL 数据库提供了慢SQL 日志功能,帮助开发者获取执行时间超过一定阈值的SQL 语句列表,通过参数 slow_query_log 开启。开启后,系统会将执行时间超过 long_query_time 的SQL 语句记入慢SQL 日志中,默认时长为10秒。
MySQL 支持两种慢SQL 日志保存格式:Table 和 File。Table的优势在于能够直接使用SQL进行查看,但是值得注意的是,因为默认使用的是mysiam引擎,如果使用Xtrabackup备份,慢SQL数量过多可能会导致实例长时间的不可写,所以要定时清理。
除了超时SQL 语句,没有被索引覆盖的SQL 语句同样值得开发者关注,通过long_queries_not_using_indexes,开发者可以在慢日志中捕获这些SQL。为了控制慢日志的写入频率,log_throttle_queries_not_using_indexes 规定了每分钟因为没有走索引而记入慢SQL 日志的查询数。远程控制软件
MySQL 还提供了参数 log_slow_admin_statements 控制管理类型的SQL 语句是否记入慢SQL 日志,例如 ALTER TABLE,ANALYZE TABLE 等。
另外,min_examined_row_limit 规定了所有记入慢日志的SQL 最小的行扫描记录数,只有扫描记录数大于该值的SQL 才会被记入日志。默认值为0,建议开发者将其设置为100,如果扫描记录数很少,说明该SQL 已经没有优化的空间了。
此外,慢SQL 作为衡量数据库访问速度的一个重要指标,可以通过执行 show global status like ‘Slow_queries’ 来监控其数量的变化。如果在某个时间段内,数据库的慢SQL 数量出现急剧增长,开发者就需要关注该时间段内的慢SQL 语句,进行SQL 语句排查。
除了慢SQL 语句,系统中执行次数最多、扫描记录数最多、执行时间最长的SQL 语句,都可以作为SQL 优化的对象。
在 MySQL 5.7 的 sys 库的 statement_analysis 视图中,整理了所有来自用户的SQL 语句。
由于SQL 的执行计划与SQL 包含的具体参数取值无关,所以通过将格式相同,仅参数取值不同的SQL 归类,可以提高开发者的检索效率。
按照 exec_count、latency、rows_examined 三个字段分别排序,即可获取执行次数最多、执行时间最长、扫描记录数最多的SQL 语句列表。
第二步:跟踪执行过程
明确了优化对象,接下来,就是追踪这些SQL 语句的执行过程,这需要我们采集如下关键指标:
○ 索引:通过执行 explain SQL 语句,获取SQL 的执行计划。key 字段标识了该SQL 语句是否通过索引扫描记录,如果该字段为 NULL,且扫描记录数较多,则预示可以通过新建索引来优化执行效率。
○ 扫描记录数:慢日志的 rows_examined 字段,标识了该SQL 语句扫描的记录数,扫描记录数越多,表示该SQL 语句执行花销越大,执行效率越低。
○ 持锁时间:慢日志的 lock_time 字段标识了该SQL 语句因为锁等待浪费的时间,如果该值较大,说明SQL 语句存在较多的等待和锁冲突。
○ 返回记录数:慢日志的 rows_sent 字段标识该条SQL 语句的返回记录条数,返回记录过多,对系统资源的消耗也越多。
除了上述几个关键指标外,在网易(c.163.com)维护的 MySQL 分支版本 InnoSQL 中,还增加了针对某条SQL 语句的 IO 开销统计。在慢日志中增加了 logical reads 和 physical reads 两个字段,分别表示该SQL 语句读取数据库缓存和产生实际硬盘 IO 的次数。
第三步:分析优化方案
掌握了这些关键运行指标,接下来就是进行分析优化的过程。
没有覆盖索引:对于没有被索引覆盖的SQL 语句的过滤条件涉及的字段,在区分度较大的字段上创建索引,如果涉及多个字段,尽量创建联合索引。需要注意的是,SQL 语句在一些情况下是无法使用索引的,例如使用!<>判断等,此时应修改SQL 语句逻辑。
SQL 语句被索引覆盖,但是扫描记录数非常多,返回记录数不多:此时要考虑索引是否高效。衡量索引效率的一个判断标准是索引的区分度,通过mysql 库下 innodb_index_stats 表的 stat_value 字段,我们可以知道该表在该索引涉及列上取值不同的记录数,然后与 n_rows 表中记录的该表总记录数相除,即可得到该表的区分度。越接近1,表示区分度越高,低于0.1,则说明区分度较差。开发者应该重新评估SQL 语句涉及的字段,选择区分度高的多个字段创建索引。
SQL 语句被索引覆盖,扫描记录数非常多,返回记录数也非常多:除了索引效率的问题,也有可能是因为SQL 语句本身过滤条件不强,导致返回的记录数过多。此时,开发者应该从业务层修改SQL 语句,增加SQL 过滤条件。
除了上述指标的特征外,由于索引的创建在插入、更新、删除数据时会带来索引维护的开销,所以我们必须尽可能地精简索引的数量,可以通过如下方式实现:
○ 去除冗余索引: 通过 MySQL sys 库下的 schema_redundant_indexes 视图,可以查看当前实例有哪些冗余索引。
○ 合并多个索引:对于已经创建的索引,如果多个索引涉及字段顺序一致,且索引的第一个字段相同,则可以组成一个联合索引。例如索引(a,c)和索引(a,d),可以组成联合索引(a,c,d)。值得注意的是,合并的两个索引的第一个字段必须相同,因为联合索引的第一个字段必须要出现在查询条件中,否则查询不能使用该索引。
○ 去除无效索引:通过 MySQL sys 库下的 schema_unused_indexes 视图,可以查看当前实例哪些索引从来没有被使用。
至此就完成了SQL 优化的整个过程。
经过上文的介绍大家可以看出,SQL 优化,尤其是执行计划分析的过程,十分依赖开发人员的数据库基础和调优经验,为了降低开发者的使用门槛,网易云基础服务集成网易10年的数据库开发以及优化经验,推出SQL 优化专家系统。
网易云基础服务 SQL 优化专家系统
慢SQL 功能可以实时监控数据库的慢SQL 数量变化,自动锁定超过阈值的时间范围,同时提供了对应时间范围内CPU 和IO 负载视图。
点击锁定的时间范围,检索该时间段内所有的SQL 语句,SQL 语句进行了格式化处理。
点击某条SQL 语句,专家系统会自动收集SQL 执行过程的关键指标,给出优化建议。
SQL 排行榜功能则从执行次数、响应时间和扫描记录数的角度整理了所有SQL。
热表功能是网易云基础服务推出的一个通过分析表的访问特点,针对表进行优化的功能。
举例来看,在电商的业务架构中,数据库有多种用途。对于存储商品信息的数据库表,读请求远远多于写请求,对于读多写少的业务,专家系统会推荐开发者在数据库前端增加缓存,或者创建只读从节点,通过读写分离技术来扩展数据库的读能力。对于存储交易流水、用户足迹的业务,插入数据较为集中,专家系统会建议用户使用批量插入的方式 insert into table values()()() 来提高插入效率,避免每次插入都需要数据库反复解析SQL 语句,生成执行计划的过程开销。对于一些要求实时插入的场景,专家系统会推荐开发者使用插入效率更高的 tokuDB 存储引擎作为 MySQL 数据存储的解决方案。
热表功能的另外一个作用就是预热。新建只读从节点,为了防止业务切入新建节点后,节点没有缓存热点数据,导致请求直接访问硬盘,访问延迟增加,开发者可以通过热表功能锁定热点数据,预先将这些数据扫描到内存中。
对SQL 优化,提升性能!的更多相关文章
- 如何利用Nginx的缓冲、缓存优化提升性能
使用缓冲释放后端服务器 反向代理的一个问题是代理大量用户时会增加服务器进程的性能冲击影响.在大多数情况下,可以很大程度上能通过利用Nginx的缓冲和缓存功能减轻. 当代理到另一台服务器,两个不同的连接 ...
- selenium 优化 提升性能
结果: 用时:7.200437545776367s用时:5.909301519393921s headless用时:4.924464702606201s headless\phone用时:4.9358 ...
- mysql配置my.cnf文件,以及参数优化提升性能
系统centos7 mariadb通过yum安装 mysql配置文件位于/etc/my.cnf 常用参数: 1)max_connections设置最大连接(用户)数,其默认值为100,设置太小会出现t ...
- 智能SQL优化工具--SQL Optimizer for SQL Server(帮助提升数据库应用程序性能,最大程度地自动优化你的SQL语句 )
SQL Optimizer for SQL Server 帮助提升数据库应用程序性能,最大程度地自动优化你的SQL语句 SQL Optimizer for SQL Server 让 SQL Serve ...
- oracle 11g亿级复杂SQL优化一例(数量级性能提升)
自从16年之后,因为工作原因,项目中就没有再使用oracle了,最近最近支持一个项目,又要开始负责这块事情了.最近在跑性能测试,配置全部调好之后,不少sql还存在性能低下的问题,主要涉及执行计划的不合 ...
- SQL优化系列(三)- 用最少的索引获得最大的性能提升
从全局出发优化索引 对于高负载的数据库,如何创建最少的索引,让数据库的整体性能提高呢?例如,对于100 条SQL语句,如何创建最佳的5条索引? SQL自动优化工具SQL Tuning Expert P ...
- SQL Server中使用Check约束提升性能
在SQL Server中,SQL语句的执行是依赖查询优化器生成的执行计划,而执行计划的好坏直接关乎执行性能. 在查询优化器生成执行计划过程中,需要参考元数据来尽可能生成高效的执行计划, ...
- SQL Server数据库性能优化之SQL语句篇【转】
SQL Server数据库性能优化之SQL语句篇http://www.blogjava.net/allen-zhe/archive/2010/07/23/326927.html 近期项目需要, 做了一 ...
- 最有效地优化 Microsoft SQL Server 的性能
为了最有效地优化 Microsoft SQL Server 的性能,您必须明确当情况不断变化时,性能将在哪些方面得到最大程度的改进,并集中分析这些方面.否则,在这些问题上您可能花费大量的时间和精力 ...
随机推荐
- Arm-linux-gcc-4.3.2安装步骤 (转)
http://blog.chinaunix.net/uid-26119896-id-3302233.html 安装交叉编译工具链: 1.首先以root用户登入 2.复制arm-linux-gcc-4. ...
- 前端 CSS的选择器
什么是选择器.在一个HTML页面中会有很多很多的元素,不同的元素可能会有不同的样式,某些元素又需要设置相同的样式,选择器就是用来从HTML页面中查找特定元素的,找到元素之后就可以为它们设置样式了. 选 ...
- 堆排序 && Kth Largest Element in an Array
堆排序 堆节点的访问 通常堆是通过一维数组来实现的.在数组起始位置为0的情形中: 父节点i的左子节点在位置(2*i+1); 父节点i的右子节点在位置(2*i+2); 子节点i的父节点在位置floor( ...
- C#获取当前路径7中方法
//获取模块的完整路径. string path1 = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; //获取 ...
- oracle 实现mysql find_set_in函数
create or replace FUNCTION F_FIND_IN_SET(piv_str1 varchar2, piv_str2 varchar2, p_sep varchar2 := ',' ...
- IDEA导入Junit jar包,在JavaSE的Module中使用Junit测试
写代码时偶尔想试一下自己的小想法,于是在IDEA中建了一个JavaEE项目.JavaEE项目中只能在main方法中运行代码块,不如单元测试的@Test灵活. 于是在网上找到了Junit的jar包:Do ...
- angularJS(一):表达式、指令
简介 以 JavaScript 编写的库,是一个 JavaScript 框架 一.表达式 AngularJS 使用 表达式 把数据绑定到 HTML. 表达式写在双大括号内:{{ expression ...
- 【源码解读】pix2pix(一):训练
源码地址:https://github.com/mrzhu-cool/pix2pix-pytorch 相比于朱俊彦的版本,这一版更加简单易读 训练的代码在train.py,开头依然是很多代码的共同三板 ...
- git error: failed to push some refs to 'git@github.com:xxx/xxx.git'
本地仓库中和远程仓库不一致,缺少readme.md文件 解决方式参见:https://blog.csdn.net/qq_37281252/article/details/79044798
- iOS APP 国际化
pp Store 中很多流行的应用程序有多种语言版本.虽然这些应用程序可能因为很多因素而变得流行,但是具有多种本地化版本,肯定是其中一个因素.越多的人可以理解并使用您的应用程序,潜在的买家也就越多. ...