从0开始回顾MySQL---系列九

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS AI 助手,专业版
简介: SQL优化1、一条sql语句执行很慢的原因有哪些? ⚡ 一个SQL执行的很慢,我们要分两种情况讨论:1. 大多数情况下很正常,偶尔很慢,则有如下原因:● 数据库在刷新脏页(内存数据页跟磁盘数据页内容不一致的时候,我们称这个内存页为“脏页),例如redo log 写满了需要同步到磁盘。 ● 执行的时候,遇到锁,如表锁、行锁。 ● sql语句写的不好。 2. 这条SQL语句一直执行的很慢,则有如下原因:● 没有用上索引或者索引失效:比如该字段没有索引,由于对字段进行运算、函数操作导致无法用索引。 ● 有索引可能会走全表扫描: ○ 怎样判断是否走全表扫描? ○ 某

SQL优化


1、一条sql语句执行很慢的原因有哪些?


一个SQL执行的很慢,我们要分两种情况讨论:

  1. 大多数情况下很正常,偶尔很慢,则有如下原因
  • 数据库在刷新脏页(内存数据页跟磁盘数据页内容不一致的时候,我们称这个内存页为“脏页),例如redo log 写满了需要同步到磁盘。
  • 执行的时候,遇到锁,如表锁、行锁。
  • sql语句写的不好。
  1. 这条SQL语句一直执行的很慢,则有如下原因
  • 没有用上索引或者索引失效:比如该字段没有索引,由于对字段进行运算、函数操作导致无法用索引。
  • 有索引可能会走全表扫描:
  • 怎样判断是否走全表扫描?
  • 某一列中不重复数据的个数称为基数,而数据量大时不可能全部扫描一遍得到基数,而是采样部分数据进行预测,那有可能预测错了,导致走全表扫描。
  • MySQL的索引都是排好序的。如果区分度高排序越快,区分度越低,排序慢;  

2、慢SQL如何定位呢?


慢SQL的监控主要通过两个途径:

  • 慢查询日志 :开启MySQL的慢查询日志,再通过一些工具比如mysqldumpslow去分析对应的慢查询日志,当然现在一般的云厂商都提供了可视化的平台。
  • 服务监控 :可以在业务的基建中加⼊对慢SQL的监控,常见的方案有字节码插桩、连接池扩展、ORM框架过程,对服务运行中的慢SQL进行监控和告警。
-- 查看慢查询日志配置信息
show variables like ‘slow_query%’;
-- 开启慢查询日志
set global slow_query_log = on;

3、explain执行计划


对于低性能的SQL语句的定位,最重要也是最有效的方法就是使用执行计划,MySQL提供了explain命令来查看语句的执行计划。

explain的作用

  1. 描述 MySQL 如何执行查询操作、执行顺序,使用到的索引,以及 MySQL 成功返回结果集需要执行的行数。
  2. 可以帮助我们分析 select 语句,让我们知道查询效率低下的原因,从而改进我们的查询,让查询优化器能够更好的工作。

语法

explain + select 语句;


在执行计划中,我们重点关注以下几列:

1、ID列 一组数字,表示 sql 语句中 select 的执行顺序,有几个 select 就有几个 id,按照 select 出现的顺序呈现结果。

  • id 相同,执行顺序由上而下;
  • id 不同,序号会递增。值越大优先级越高,就越先执行。

2、select_type 列:查询语句的类型

  • simple   简单查询;
  • primary 复杂查询;
  • subquery 子查询,在 select 中的子查询(不在 from 子句中);
  • derived 衍生查询,在 from 子句中子查询,MySQL 会将结果存放在一个临时表中,也称为派生表(derived 的英文含义)

3、type 列:表关联类型或访问类型,重要的一列,是判断查询是否高效的一句:也就是 MySQL 决定如何查找表中的行就看这个列。

type类型

解释

ALL

全表扫描,性能极差

index

全索引扫描,跟 ALL 差不多,不同的是 index 是扫描整棵索引树,比 ALL 要快些。

range

范围扫描,通常出现在 in (), between ,> ,<, >= 等操作中。使用一个索引来检索给定范围的行。

ref

索引查找,不使用唯一索引,使用普通索引或者唯一性索引的部分前缀,索引要和某个值相比较,可能会找到多个符合条件的行。

eq_ref

最多只返回一条符合条件的记录。在使用唯一性索引或主键查找时会出现该值,非常高效。

const/system

该表至多有一个匹配行,在查询开始时读取,或者该表是系统表,只有一行匹配。其中 const 用于在和 primary key 或 unique 索引中有固定值比较的情形。

  • ALL 是最差的,system 是最好的,性能最佳,阿里巴巴开发规约中要求最差也得到 range 级别,而不能有 index、ALL。

4、Extra 列:额外信息,也非常重要

  • Using index:使用覆盖索引,表示查询索引就可查到所需数据,不用回表,说明性能不错。
  • Using where:在存储引擎检索行后再进行过滤,就是先读取整行数据,再按 where 条件进行取舍。
  • Using temporary:mysql 需要创建一张临时表来处理查询,一般是因为查询语句中有排序、分组、和多表 join 的情况,一般是要进行优化的。
  • Using filesort:文件排序,一般在内存中进行排序,占用CPU较多。如果待排结果较大,会产生临时文件I/O到磁盘进行排序,效率较低

4、MySQL优化


索引

  1. 尽量使用 覆盖索引 进行查询,避免 回表 带来的性能损耗。(一个索引包含(覆盖)所有需要查询字段的值,被称之为"覆盖索引")
  2. 组合索引符合最左匹配原则;
  3. 写多读少,选用普通索引更好,可以利用change buffer进行性能优化减少磁盘lO,将更新操作记录到change bufer,等查询来了将数据读到内存再进行修改;
  4. 尽量避免索引失效
  5. 索引建立原则:
  • 为列的基数大的列创建索引;
  • 索引列的类型尽量小;
  • 只为用于搜索、排序或分组的列创建索引;
  • 尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。
  • 为了尽可能少的让 聚簇索引 发生页面分裂和记录移位的情况,建议让主键拥有 AUTO_INCREMENT 属性。
  • 对于插入、更新、删除等 DML 操作比较频繁的表,不适合建立索引

SQL语句

  1. 不使用 SELECT * 查询,而是使用 SELECT <字段列表> 查询;
  2. WHERE 从句中不对列进行函数转换和计算(避免索引失效);
  3. 避免数据类型的隐式转换( 隐式转换会导致索引失效如:  where id = '111')
  4. 避免使用 JOIN 关联太多的表( 对于关联操作来说,会产生临时表操作,影响查询效率  )

  1. 使用较低的隔离级别 ,因为隔离级别越低,事务请求的锁越少;
  2. 不同的程序访问一组表的时候,应尽量约定一个相同的顺序访问各表,对于一个表而言,尽可能的固定顺序的获取表中的行,这样可以大大的减少死锁的机会;
  3. 尽量控制事务大小,减少锁定资源量和时间长度;
  4. 数据查询的时候不是必要,不要使用加锁。MySQL的MVCC可以实现事务中的查询不用加锁,优化事务性能:MVCC只在committed read(读提交)和 repeatable read (可重复读)两种隔离级别  。

数据库结构优化

  1. 考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表。  
  2. 对于经常联合查询的表,可以考虑建立中间表

5、超大分页查询如何优化?

问题:

select * from table where age > 20 limit 1000000,10;  -- age有索引

需要加载一百万条数据,然后基本上全部丢弃,取10条。

说明MySQL并不是跳过offset行,而是取offset+N行,然后返回放弃前offset行,返回N行,那当offset特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行SQL改写。

如何解决?

利用延迟关联或者主键阈值法优化超多分页场景。

  1. 延迟关联法
  • 我们先查询出符合要求的主键( 由于查询的字段有索引,该索引的叶子节点就是主键,通过索引覆盖我们可以省去一次回表操作)
    然后再通过主键索引查询数据,这就省去了遍历数据找初始位置数据的过程。
select * from table where id in (select id from table where age > 20)limit 1000000,10;

2. 主键阈值法

  • 如果你的主键是自增的,那么就可以通过条件推算出符合条件的主键最大值&最小值(这里也是通过索引覆盖省去了一次回表操作)
    然后再根据阈值,取数据即可,同样省去了遍历数据找初始位置数据的过程 。
select * from table where id >= (select id from table where age > 20 limit 1000000, 1) limit 10;

总结: 无论是延迟关联法,还是主键阈值法。思想都是一样的,先把符合条件的主键找到,然后通过主键去定位符合条件的数据,这里优化了2个点:

  1. 通过索引覆盖避免了回表;
  2. 通过主键直接定位数据的方法,省去了在数据集中查询初始位置的过程。

当然还有其他的解决方法,比如说我们可以将数据可预测性的提前缓存到Redis中,等到查询时,直接返回即可。

6、为什么select * 会导致查询效率低?

  1. 不需要的列会增加数据传输时间和网络开销:
  • 用SELECT * 数据库需要解析更多的对象、字段、权限、属性等相关内容,在 SQL 语句复杂,硬解析较多的情况下,会对数据库造成沉重的负担。
  • 增大网络开销,* 有时会误带上如log、IconMD5之类的无用且大文本字段,数据传输size会几何增涨。如果DB和应用程序不在同一台机器,这种开销非常明显。即使 MySQL 服务器和客户端是在同一台机器上,使用的协议还是 tcp,通信也是需要额外的时间。
  1. 对于无用的大字段,如 varchar、blob、text,会增加 io 操作:
  • 如果记录中包含超过 728 字节的数据,MySQL 将这些数据存储在一个额外的位置,并在记录中保存一个指向这些数据的指针。这意味着在读取记录时,MySQL 需要执行额外的一次 I/O 操作来获取超过 728 字节的数据。
  1. 失去MySQL优化器“覆盖索引”策略优化的可能性:
  • SELECT * 杜绝了覆盖索引的可能性,而基于MySQL优化器的“覆盖索引”策略又是速度极快,效率极高,业界极为推荐的查询优化方式。
  • 如果用户使用select *,获取了不需要的数据,则首先通过非聚簇索引过滤数据,然后再通过聚集索引获取所有的列,这就多了一次b+树查询,速度必然会慢很多。
  • 由于辅助索引的数据比聚集索引少很多,很多情况下,通过辅助索引进行覆盖索引(通过索引就能获取用户需要的所有列),都不需要读磁盘,直接从内存取,而聚集索引很可能数据在磁盘(外存)中(取决于buffer pool的大小和命中率),这种情况下,一个是内存读,一个是磁盘读,速度差异就很显著了,几乎是数量级的差异。
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
负载均衡 安全 应用服务中间件
什么是正向代理和反向代理
正向代理是客户端与服务端之间的中介,用于访问受限资源,如V/P/N和动态IP代理,同时可隐藏客户端IP。反向代理则接收客户端请求并转发给后端服务器集群,隐藏真实服务器信息,常用于堡垒机和负载均衡,如nginx。正向代理焦点在客户端,反向代理关注服务端。
|
弹性计算 监控 API
新浪微博上云实践:极端流量下的峰值应对与架构挑战
在混合云架构中,核心关键是专线,它是实现内部与公有云之间弹性的核心。目前微博和阿里云之间已经拉通了多条专线,日常的核心消息通过多机房的消息组件同步到阿里云缓存中,实现前端层面和缓存层面的弹性伸缩。在混合云的模式下,微博目前采用了两种部署方案。
9190 0
|
定位技术 数据中心 网络架构
如何使用网络拓扑管理IT?
网络拓扑结构反映出网络的结构关系,它对于网络的性能、可靠性以及建设管理成本等都有着重要的影响,因此网络拓扑结构的设计在整个网络设计中占有十分重要的地位,在网络构建时,网络拓常见的网络拓扑结构有总线型、星型、环型、树型和网状型等
977 0
如何使用网络拓扑管理IT?
|
Java 关系型数据库 MySQL
MySQL 分库分表方案
本文总结了数据库分库分表的相关概念和实践,针对单张表数据量过大及增长迅速的问题,介绍了垂直和水平切分的方式及其适用场景。文章分析了分库分表后可能面临的事务支持、多库结果集合并、跨库join等问题,并列举了几种常见的开源分库分表中间件。最后强调了不建议水平分库分表的原因,帮助读者在规划时规避潜在问题。
1231 20
|
PHP
PHP微信公众号投票活动系统源码
PHP微信公众号投票活动系统源码
500 11
|
人工智能 自然语言处理 Java
Spring Cloud Alibaba AI 入门与实践
本文将介绍 Spring Cloud Alibaba AI 的基本概念、主要特性和功能,并演示如何完成一个在线聊天和在线画图的 AI 应用。
4295 8
|
供应链 安全 分布式数据库
探索区块链技术:从原理到应用的全面解析
【10月更文挑战第22天】 本文旨在深入浅出地探讨区块链技术,一种近年来引起广泛关注的分布式账本技术。我们将从区块链的基本概念入手,逐步深入到其工作原理、关键技术特点以及在金融、供应链管理等多个领域的实际应用案例。通过这篇文章,读者不仅能够理解区块链技术的核心价值和潜力,还能获得关于如何评估和选择适合自己需求的区块链解决方案的实用建议。
1126 0
|
SQL 微服务
成功解决 :status 500 reading CouponFeignService#saveSpuBounds(SpuBoundTo)
这篇文章讲述了作者在微服务项目开发中遇到的一个具体问题:使用Feign进行远程服务调用时出现了`status 500`错误。文章详细描述了排查过程,包括检查Feign配置和被调用服务的日志信息,最终确定问题是由于Lombok插件的`@Data`注解导致。作者通过将`@Data`注解注释掉并手动生成get、set方法解决了问题,并提供了成功调用远程服务后的截图。
成功解决 :status 500 reading CouponFeignService#saveSpuBounds(SpuBoundTo)
|
存储 关系型数据库 MySQL
MySQL各字符集、排序规则的由来、用法,区别和联系
MySQL支持多种字符集和排序规则,这些在数据库设计和数据处理中起着重要作用。下面是它们的由来、用法、区别和联系: 1. **字符集(Character Set)**: - **由来**:字符集定义了数据库中可以存储的字符集合,以及这些字符在数据库中的存储方式。 - **用法**:在创建数据库或表时,可以指定所需的字符集。常见的字符集包括UTF-8、UTF-16、Latin1等。 - **区别和联系**:不同的字符集支持不同的字符范围和存储方式,选择合适的字符集可以确保数据的正确存储和处理。例如,UTF-8支持全球范围内的大多数字符,而Latin1只支持西欧语言字符集。
457 1
|
数据管理 开发工具 NoSQL
mongo-connector实现MongoDB与elasticsearch实时同步深入详解
mongo-connector工具创建一个从MongoDB簇到一个或多个目标系统的管道,目标系统包括:Solr,Elasticsearch,或MongoDB簇。
2339 0

热门文章

最新文章