SQL优化(基础的整理)

举报
窗台 发表于 2020/10/29 23:49:20 2020/10/29
【摘要】 对于低性能的SQL语句的定位,最重要也是最有效的方法就是使用执行计划,MySQL提供了explain命令来查看语句的执行计划。 不管是哪种数据库,或者是哪种数据库引擎,在对一条SQL语句进行执行的过程中都会做很多相关的优化,对于查询语句,最重要的优化方式就是使用索引。 而执行计划,就是显示数据库引擎对于SQL语句的执行的详细情况,其中包含了是否使用索引,使用什么索引,使用的索引的相关信息等。...

对于低性能的SQL语句的定位,最重要也是最有效的方法就是使用执行计划,MySQL提供了explain命令来查看语句的执行计划。 不管是哪种数据库,或者是哪种数据库引擎,在对一条SQL语句进行执行的过程中都会做很多相关的优化,对于查询语句,最重要的优化方式就是使用索引。 而执行计划,就是显示数据库引擎对于SQL语句的执行的详细情况,其中包含了是否使用索引,使用什么索引,使用的索引的相关信息等

image.png

执行计划包含的信息 id 有一组数字组成。表示一个查询中各个子查询的执行顺序;

      • id相同执行顺序由上至下。

      • id不同,id值越大优先级越高,越先被执行。

      • id为null时表示一个结果集,不需要使用它查询,常出现在包含union等查询语句中。

select_type 每个子查询的查询类型,一些常见的查询类型。

id select_type 
description
1 SIMPLE
不包含任何子查询或union等查询
2 PRIMARY
包含子查询外层查询就显示为PRIMARY
3 SUBQUERY 在select或where字句中包含的查询
4 DERIVED
form字句中包含的查询
5 UNION
出现在union后的查询语句中

table 查询的数据表,当从衍生表中查数据时会显示 x 表示对应的执行计划id partitions 表分区、表创建的时候可以指定通过那个列进行表分区。 举个例子:

create table tmp (
    id int unsigned not null AUTO_INCREMENT,
    name varchar(255),
    PRIMARY KEY (id)) engine = innodbpartition by key (id) partitions 5;
      • ALL 扫描全表数据

      • index 遍历索引

      • range 索引范围查找

      • index_subquery 在子查询中使用 ref

      • unique_subquery 在子查询中使用 eq_ref

      • ref_or_null 对Null进行索引的优化的 ref

      • fulltext 使用全文索引

      • ref 使用非唯一索引查找数据

eq_ref 在join查询中使用PRIMARY KEYorUNIQUE NOT NULL索引关联。

    possible_keys 可能使用的索引,注意不一定会使用。查询涉及到的字段上若存在索引,则该索引将被列出来。当该列为 NULL时就要考虑当前的SQL是否需要优化了。

    key 显示MySQL在查询中实际使用的索引,若没有使用索引,显示为NULL。

    TIPS:查询中若使用了覆盖索引(覆盖索引:索引的数据覆盖了需要查询的所有数据),则该索引仅出现在key列表中

    key_length 索引长度

    ref 表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值

    rows 返回估算的结果集数目,并不是一个准确的值。

extra 的信息非常丰富,常见的有:

          1. Using index 使用覆盖索引

          2. Using where 使用了用where子句来过滤结果集

          3. Using filesort 使用文件排序,使用非索引列进行排序时出现,非常消耗性能,尽量优化。

          4. Using temporary 使用了临时表 sql优化的目标可以参考阿里开发手册

SQL的生命周期?

          1. 应用服务器与数据库服务器建立一个连接

          2. 数据库进程拿到请求sql

          3. 解析并生成执行计划,执行

          4. 读取数据到内存并进行逻辑处理

          5. 通过步骤一的连接,发送结果到客户端

          6. 关掉连接,释放资源

image.png


大表数据查询

          1. 优化shema、sql语句+索引;

          2. 第二加缓存,memcached, redis;

          3. 主从复制,读写分离;

          4. 垂直拆分,根据你模块的耦合度,将一个大的系统分为多个小的系统,也就是分布式系统;

          5. 水平切分,针对数据量大的表,这一步最麻烦,最能考验技术水平,要选择一个合理的sharding key, 为了有好的查询效率,表结构也要改动,做一定的冗余,应用也要改,sql中尽量带sharding key,将数据定位到限定的表上去查,而不是扫描全部的表;

为什么要尽量设定一个主键?

主键是数据库确保数据行在整张表唯一性的保障,即使业务上本张表没有主键,也建议添加一个自增长的ID列作为主键。设定了主键之后,在后续的删改查的时候可能更加快速以及确保操作数据范围安全。

字段为什么要求定义为not null?

null值会占用更多的字节,且会在程序中造成很多与预期不符的情况。

优化查询过程中的数据访问

          • 访问数据太多导致查询性能下降

          • 确定应用程序是否在检索大量超过需要的数据,可能是太多行或列

          • 确认MySQL服务器是否在分析大量不必要的数据行

          • 避免犯如下SQL语句错误

          • 查询不需要的数据。解决办法:使用limit解决

          • 多表关联返回全部列。解决办法:指定列名

          • 总是返回全部列。解决办法:避免使用SELECT *

          • 重复查询相同的数据。解决办法:可以缓存数据,下次直接读取缓存

          • 是否在扫描额外的记录。解决办法:

          • 使用explain进行分析,如果发现查询需要扫描大量的数据,但只返回少数的行,可以通过如下技巧去优化:

          • 使用索引覆盖扫描,把所有的列都放到索引中,这样存储引擎不需要回表获取对应行就可以返回结果。

          • 改变数据库和表的结构,修改数据表范式

          • 重写SQL语句,让优化器可以以更优的方式执行查询。

优化长难的查询语句

          • 一个复杂查询还是多个简单查询

          • MySQL内部每秒能扫描内存中上百万行数据,相比之下,响应数据给客户端就要慢得多

          • 使用尽可能小的查询是好的,但是有时将一个大的查询分解为多个小的查询是很有必要的。

          • 切分查询

          • 将一个大的查询分为多个小的相同的查询

          • 一次性删除1000万的数据要比一次删除1万,暂停一会的方案更加损耗服务器开销。

          • 分解关联查询,让缓存的效率更高。

          • 执行单个查询可以减少锁的竞争。

          • 在应用层做关联更容易对数据库进行拆分。

          • 查询效率会有大幅提升。

          • 较少冗余记录的查询。

优化子查询

          • 用关联查询替代

          • 优化GROUP BY和DISTINCT

          • 这两种查询据可以使用索引来优化,是最有效的优化方法

          • 关联查询中,使用标识列分组的效率更高

          • 如果不需要ORDER BY,进行GROUP BY时加ORDER BY NULL,MySQL不会再进行文件排序。

          • WITH ROLLUP超级聚合,可以挪到应用程序处理


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。