SQL 优化|学习笔记

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 快速学习 SQL 优化

开发者学堂课程【云数据库优化经典案例:SQL 优化】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址https://developer.aliyun.com/learning/course/67/detail/1159


SQL 优化

内容简介:

一、分页优化案例

二、子查询优化案例

三、SQL 优化最佳实践


一、分页优化案例

SQL 优化主要是两个案例,第一个是分页优化案例。

图片5.png

上图就是一个案例,可以看到上述数据库,它的 IOPS 是百分之百,但是 CPU、QPS 和连接数值都非常低。因为处理了 IO,它也是被 SQL 占用的。这时去看数据库到底运营行怎样的 SQL ?可以看到数据库运行的 SQL 已经有51秒,一直在 Sending data,这个 SQL其实就是商家导订单的一个 SQL,在分页去导订单。卖家可能是一个非常大的卖家,订单非常多,所以去通过分页去导订单。其实可以看到 SQL 执行的非常慢,数据库中堆积非常多的 SQL。那 SQL 是否可以优化?由上图可以看到此 SQL,前提条件是表中已经有 sellerId 和  gmt_ modified  的索引。

图片6.png

普通写法:

select * from buyer where sellerid=100 limit 10000o , 5000

普通 limit M,N 的翻页写法,在越往后翻页的过程中速度越慢,原因是 mysql 会读取表中的前 M+N 条数据,M 越大,性能就越差。

这个  SQL 其实是一个普通分页写法,在普通的翻页写法里可能会有的问题;普通limit M,N 的翻页写法存在一个问题,就是越往后翻页的过程中速度越慢,因为 MySQL  翻译时不需要把前面 limit 中第一个数据(m)读出来,然后再去读(n)真要去翻译函数的数据,所以随着 M 越大,就是前面翻页第一位的数字越大,后面的性能可能就会越来越差。在以前 BBS 论坛较火的时候,那时其实很多论坛就是翻页写法,采用 limit M,N 的写法。如果论坛前面的几个帖子是热帖,它前面几页访问都是非常快的,但是到后面随着越往后翻页,性能就越来越慢。问题就是最终的 SQL 写法采用了普通写法。随着M,也就是翻译的第一个数字越大,性能会越来越差,那这个 SQL 写法如何优化?

优化写法:

select t1.* from buyer t1.

(select id from buyer sellerid=100 limit 100000,5o00) t2where t1.id=t2.id;

在淘宝以前前台的翻页,比如商品详情页面,其实也有类似的翻译,普通的翻页写法是不能在淘宝前端的,写法上必须经过优化的,那下面这个写法就是淘宝 SQL 翻页的规范。这个规范是怎样实施的?我们可以看到 SQL 首先是查出 id ,这个 id  是真正要去翻译一个5000行的 id。那这里有什么好处?就是说查询这个 id,真正要翻译的。取得5000行的数据,这个数据是在索引里查询,因为这个表里已经有对应 id 的索引,所以查询这5000行 id 时不需要查询前面的10万行数据,先查询5000行 id,再和主表做关联。优化后的写法和原写法的代价有所区别,原来需要查询前面的十万行数据,再去查需要的五千行数据,优化后只需查询这5000行 id 再和原表做关联。这就体现出了分页的优势。需要注意的就是,子查询里的 id 一定在索引里,覆盖索引去查询,不能回表。

注意:需要在 t 表的 sellerid 字段上创建索引,id 为表的主键create index ind_sellerid on buyer(sellerid);

图片7.png

上图是一个分页优化的案例,上面是原写法,下面是优化后的写法,先查 id 再去和主表关联,这样他的执行时间就可以从60秒降低到0.2秒。所以我们可以看到前面这种普通写法查询了大量无效数据,通过优化后的写法扫描的真实的数据大量减少。

这就是我们 SQL 优化里的第一个案例,就是分页优化,这是淘宝数据库开发里很重要的一个点。


二、子查询优化案例

下面一个就是子查询的一个案例,这个也是一个非常典型的案例。

典型子查询:

SELECT first_name

FROM employees

WHERE emp_no IN

(SELECT emp_no FROM salaries_2000 WHERE salary = 5000);

MySQ L的处理逻辑是遍历 employees 表中的每一条记录,代入到子查询中中去

改写子查询:

SELECT first_name

FROM employees emp,

(SELECT emp_no FROM salaries_2000 WHERE salary = 5000) sal

WHERE emp.emp_no = sal.emp_no;

在2014年时,一个大项目中把系统从 orcle 迁到 mysql 上面,时间是在周六,选在周六是因为访客人数相对少一点,系统迁到 mysql 后,当时的系统是5.5,在迁移后,发现 MySQL 集群全部挂掉了,经过分析,发现集群出现 SQL 堆积的问题,因为 MySQL 里处理子查询和 orcle 里处理子查询是完全不一样的原理,导致了当时集群瘫痪这样一个问题。在2010年去 IOE 的时候,也是从大型的 orcle 迁移到 mysql 里面。

可以看到子查询的原理。这个 SQL 是查询薪水为5000块的员工名字,所以,他先去查薪水表,再和 employee 表做关联。所以,这个子查询,正常逻辑是把5000块钱薪水的员工号查出再和主表 employee 表做关联。但在 MySQL 里面,它的优化器支持嵌套循环,通过 A 表驱动 B 表,如果 A 表非常大,那么这个循环次数就非常多,所以这个时候 mysql 的优化器决定了sql 执行的的顺序,在执行 SQL 的时候,从外部employee 表循环去带对应值到子查询里面所以这个 SQL 不是同我们想象的执行顺序,查出5000块薪水的员工号再和 employee 表做关联。当外部的驱动表非常大就会导致遍历到子查询里的次数非常多进而导致性能下降。所以当时把 SQL 进行了改造,把子查询数据提出来,先算出结果级,把子查询往前提和 employee 表放成同一个位置,这样 SQL 的执行速度就快了。

所以在遇到这样的子查询时,要做 SQL 的改写,这里要特别注意。那这个问题通过一个改写,从1200秒缩短为0.1秒,执行速度迅速提升。子查询是在5.1、5.5版本中存在一个较大风险,需要把这个子查询改写为关联,5.6版本后,则不需要再改写子查询。


三、SQL优化最佳实践

1、分页优化

采用高效的 Limit 写法,避免分页查询给数据库带来性能影响

2、子查询优化

子查询在5.1,5.5版本中都存在较大风险,将子查询改为关联使用 Mysql 5.6 的版本,可以避免麻烦的子查询改写

3、查询需要的字段

避免用 SELECT* 查询所有字段数据,只查询需要的字段数据

分页优化,也需要一个高效的分页写法,避免普通的写法给数据库带来较低的性能。第三,经常有很多 SQL 做一个 SELECT * 操作,然后再做一个外层,在包一层做 COUNT * 写法,此时 MySQL 就不得不把 SELECT * 子查询中的结果查出来。比如在外面再套一层条件,那外面的条件就不能只传递到查询里面,进而导致性能的低价低效。所以第一个不要去省 * ,只需要查询需要查询的字段;第二个就是尽量把子查询外面的条件带入到查询里面。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
14天前
|
算法 数据挖掘 数据库
通过 SQL 快速使用 OceanBase 向量检索学习笔记
通过 SQL 快速使用 OceanBase 向量检索学习笔记
|
21天前
|
SQL 数据库
SQL 学习笔记 - 多表关系与多表查询
数据库多表关系包括一对多、多对多和一对一,常用外键关联。多表查询方式有隐式/显式内连接、外连接、子查询等,支持别名和条件筛选。子查询分为标量、列、行、表子查询,常用于复杂查询场景。
|
8月前
|
SQL 关系型数据库 MySQL
MySQL进阶突击系列(07) 她气鼓鼓递来一条SQL | 怎么看执行计划、SQL怎么优化?
在日常研发工作当中,系统性能优化,从大的方面来看主要涉及基础平台优化、业务系统性能优化、数据库优化。面对数据库优化,除了DBA在集群性能、服务器调优需要投入精力,我们研发需要负责业务SQL执行优化。当业务数据量达到一定规模后,SQL执行效率可能就会出现瓶颈,影响系统业务响应。掌握如何判断SQL执行慢、以及如何分析SQL执行计划、优化SQL的技能,在工作中解决SQL性能问题显得非常关键。
|
5月前
|
SQL 存储 自然语言处理
SQL的解析和优化的原理:一条sql 执行过程是什么?
SQL的解析和优化的原理:一条sql 执行过程是什么?
SQL的解析和优化的原理:一条sql 执行过程是什么?
|
7月前
|
SQL 关系型数据库 MySQL
如何优化SQL查询以提高数据库性能?
这篇文章以生动的比喻介绍了优化SQL查询的重要性及方法。它首先将未优化的SQL查询比作在自助餐厅贪多嚼不烂的行为,强调了只获取必要数据的必要性。接着,文章详细讲解了四种优化策略:**精简选择**(避免使用`SELECT *`)、**专业筛选**(利用`WHERE`缩小范围)、**高效联接**(索引和限制数据量)以及**使用索引**(加速搜索)。此外,还探讨了如何避免N+1查询问题、使用分页限制结果、理解执行计划以及定期维护数据库健康。通过这些技巧,可以显著提升数据库性能,让查询更高效流畅。
|
8月前
|
SQL 关系型数据库 MySQL
基于SQL Server / MySQL进行百万条数据过滤优化方案
对百万级别数据进行高效过滤查询,需要综合使用索引、查询优化、表分区、统计信息和视图等技术手段。通过合理的数据库设计和查询优化,可以显著提升查询性能,确保系统的高效稳定运行。
269 9
|
9月前
|
SQL Oracle 关系型数据库
如何在 Oracle 中配置和使用 SQL Profiles 来优化查询性能?
在 Oracle 数据库中,SQL Profiles 是优化查询性能的工具,通过提供额外统计信息帮助生成更有效的执行计划。配置和使用步骤包括:1. 启用自动 SQL 调优;2. 手动创建 SQL Profile,涉及收集、执行调优任务、查看报告及应用建议;3. 验证效果;4. 使用 `DBA_SQL_PROFILES` 视图管理 Profile。
|
10月前
|
SQL Oracle 数据库
使用访问指导(SQL Access Advisor)优化数据库业务负载
本文介绍了Oracle的SQL访问指导(SQL Access Advisor)的应用场景及其使用方法。访问指导通过分析给定的工作负载,提供索引、物化视图和分区等方面的优化建议,帮助DBA提升数据库性能。具体步骤包括创建访问指导任务、创建工作负载、连接工作负载至访问指导、设置任务参数、运行访问指导、查看和应用优化建议。访问指导不仅针对单条SQL语句,还能综合考虑多条SQL语句的优化效果,为DBA提供全面的决策支持。
231 11
|
11月前
|
SQL 缓存 监控
大厂面试高频:4 大性能优化策略(数据库、SQL、JVM等)
本文详细解析了数据库、缓存、异步处理和Web性能优化四大策略,系统性能优化必知必备,大厂面试高频。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:4 大性能优化策略(数据库、SQL、JVM等)
|
9月前
|
SQL 分布式计算 Java
Spark SQL向量化执行引擎框架Gluten-Velox在AArch64使能和优化
本文摘自 Arm China的工程师顾煜祺关于“在 Arm 平台上使用 Native 算子库加速 Spark”的分享,主要内容包括以下四个部分: 1.技术背景 2.算子库构成 3.算子操作优化 4.未来工作
955 0