首页 > 数据库 >MySQL的SQL语句优化

MySQL的SQL语句优化

时间:2023-09-27 13:44:06浏览次数:51  
标签:语句 分区 SQL 查询 索引 MySQL 执行 id select

一、拿到SQL之后,用执行计划查看参数。

explain
select 1 from `d_ec_hyx`.`t_advertiser_info`
where 1 = 1
and f_corp_id = 15930142
and f_type in (1, 4)
and f_refund_status = 1 limit 1

 

二、 执行计划 ID。

  1、id 相同,执行顺序从上往下;

  2、id 不同,如果是子查询,id 的序号会递增,id 值越大优先级越高,越先被执行;

  3、id 有相同的又有不同的 (混合式的),即两种情况都存在,id 如果相同,可以认为是一组,从上往下顺序执行;在所有组中,id 值越大,优先级越高,越先执行;

  4、id 为 null 的最后执行;比如 union 查询可能 id 为 null;

三、执行计划 select_type。查询的类型,主要是用于区分普通查询、联合查询、子查询等;

  SIMPLE:简单的 select 查询,查询中不包含子查询或者 union;

  PRIMARY:查询中包含子部分,最外层查询则被标记为 primary;

  SUBQUERY:SUBQUERY 表示在 select 或 where 列表中包含了子查询;

   MATERIALIZED:表示 where 后面 in 条件的子查询;

  UNION:若第二个 select 出现在 union 之后,则被标记为 union;

  UNION RESULT:从 union 表获取结果的 select;

四、执行计划 table。

  查询涉及到的表,直接显示表名或者表的别名;

  <unionM,N> ID 为 M 和 N 查询结果进行 union 后产生的结果;

  <subqueryN> ID 为 N 进行子查询产生的结果; 

五、执行计划 partitions。

  匹配的分区信息,如果查询基于分区表,将会显示访问的是哪个区;
  表分区:表分区是将一大表,根据条件分割成若干个小表,mysql 5.1 开始支持数据表分区,比如:某用户表的记录超过了 2 万条,那么就可以根据 id 将表分区,也可以根据时间分区,当然也可根据其他的条件分;

  比如:
  partition BY RANGE (uid) (

    partition p0 VALUES LESS THAN (10000),

    partition p1 VALUES LESS THAN (20000)

  );

  按照这种分区方案,uid 小于 10000 的所有行被保存在分区 P0 中,uid 在 10000 到 20000 的保存在 P1 中,依次类推;

六、执行计划 type【需要关注】

  访问类型,sql 查询优化中一个很重要的指标,结果值从好到坏依次是:
  system > const > eq_ref > ref > range > index > ALL
  system:const 类型的特例,基本不会出现,可以忽略不计;
  const: 表示通过索引一次就找到了,const 用于比较 primary key 或者 unique 索引,可以说是性能最好的,1;
  eq_ref:唯一索引扫描,对于每个索引键,表中只有一条记录与之匹配,常见于主键 或 唯一索引扫描,性能次之,2;
  ref:非唯一性索引扫描,返回匹配某个单独值的所有行,本质是也是一种索引访问,性能次之,3;
  range:只检索给定范围的行,使用一个索引来选择行,性能次之,4;优化最坏的情况要达到这个级别 range;
  index:Full Index Scan,索引全表扫描,把索引从头到尾扫描一遍;
  ALL:Full Table Scan,扫描全表以找到匹配的行;

七、执行计划 possible_keys。查询过程中有可能用到的索引;

八、执行计划 key【需要关注】

  实际使用的索引,如果为 NULL,则表示没有使用索引;

九、执行计划 key_len。

  实际使用到的索引长度

十、执行计划 ref。

  当使用索引列等值查询时,与索引列进行等值匹配的对象信息;

十一、执行计划 rows 扫描行数【需要关注】

  根据表统计信息或索引选用情况,大致估算出找到所需记录所需要读取的行数;

十二、执行计划 filtered。

  表示返回结果的行数占需读取行数的百分比,filtered 的值越大越好,100 是最好的情况;

十三、执行计划 Extra。【需要关注】

  十分重要的额外信息,这些额外信息有:

  1、Using filesort:
  mysql 对数据使用一个外部的文件内容进行了排序,而不是按照表内的索引进行排序读取;

  2、Using temporary:
  使用临时表保存中间结果,也就是说 mysql 在对查询结果排序时使用了临时表,比如在 order by 或 group by;
  中间 MySql 处理过程需要多处理一个临时表,一般这种情况是需要优化处理的。
  优化处理一般使用索引优化;

  3、Using index:
  表示相应的 select 操作中使用了覆盖索引(Covering Index),避免了访问表的数据行,效率高 (不去回表操作);

  4、Using where:
  使用了 where 过滤条件;

  5、select tables optimized away:
  基于索引优化 MIN/MAX 操作或者 MyISAM 存储引擎优化 COUNT (*) 操作,不必等到执行阶段再进行计算,查询执行计划生成的阶段即可完成优化;

  6. 优化建议
    1. 所有表必须使用 Innodb 存储引擎
    没有特殊要求(即 Innodb 无法满足的功能如:列存储,存储空间数据等)的情况下,所有表必须使用 Innodb 存储引擎(MySQL5.5 之前默认使用 Myisam,5.6 以后默认的为 Innodb)。
    Innodb 支持事务,支持行级锁,更好的恢复性,高并发下性能更好。

    2. 数据库和表的字符集统一使用 UTF8
    兼容性更好,统一字符集可以避免由于字符集转换产生的乱码,不同的字符集进行比较前需要进行转换会造成索引失效,如果数据库中有存储 emoji 表情的需要,字符集需要采用 utf8mb4 字符集。

    3. 所有表和字段都需要添加注释
    使用 comment 从句添加表和列的备注,从一开始就进行数据字典的维护

    4. 尽量控制单表数据量的大小,建议控制在 500 万以内。
    500 万并不是 MySQL 数据库的限制,过大会造成修改表结构,备份,恢复都会有很大的问题。
    可以用历史数据归档(应用于日志数据),分库分表(应用于业务数据)等手段来控制数据量大小

    5. 谨慎使用 MySQL 分区表
    分区表在物理上表现为多个文件,在逻辑上表现为一个表;
    谨慎选择分区键,跨分区查询效率可能更低;
    建议采用物理分表的方式管理大数据。

    6. 尽量做到冷热数据分离,减小表的宽度
    MySQL 限制每个表最多存储 4096 列,并且每一行数据的大小不能超过 65535 字节。
    减少磁盘 IO, 保证热数据的内存缓存命中率(表越宽,把表装载进内存缓冲池时所占用的内存也就越大,也会消耗更多的 IO);
    更有效的利用缓存,避免读入无用的冷数据;
    经常一起使用的列放到一个表中(避免更多的关联操作)。

    7. 禁止在表中建立预留字段
    预留字段的命名很难做到见名识义。
    预留字段无法确认存储的数据类型,所以无法选择合适的类型。
    对预留字段类型的修改,会对表进行锁定。

    8. 禁止在数据库中存储图片,文件等大的二进制数据
    通常文件很大,会短时间内造成数据量快速增长,数据库进行数据库读取时,通常会进行大量的随机 IO 操作,文件很大时,IO 操作很耗时。
    通常存储于文件服务器,数据库只存储文件地址信息

    9. 禁止在线上做数据库压力测试

    10. 禁止从开发环境,测试环境直接连接生产环境数据库

标签:语句,分区,SQL,查询,索引,MySQL,执行,id,select
From: https://www.cnblogs.com/chuhecc/p/17715673.html

相关文章

  • 27、Flink 的SQL之SELECT (Group Aggregation分组聚合、Over Aggregation Over聚合 和
    文章目录Flink系列文章一、GroupAggregation分组聚合1、count示例2、groupby的聚合示例3、distinct聚合4、GROUPINGSETS1)、ROLLUP2)、CUBE5、Having二、OverAggregation1、语法1)、ORDERBY2)、PARTITIONBY3)、RangeDefinitions4)、RANGEintervals5)、ROWintervals2、示例三、......
  • 27、Flink 的SQL之SELECT (SQL Hints 和 Joins)介绍及详细示例(2-2)
    Flink系列文章1、Flink部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接13、Flink的tableapi与sql的基本概念、通用api介绍及入门示例14、Flink的tableapi与sql之数据类型:内置数据类型以及它们的属性15、Flink的tableapi与s......
  • 27、Flink 的SQL之SELECT (窗口聚合)介绍及详细示例(4)
    文章目录Flink系列文章一、WindowTVFAggregation1、WindowingTVFs窗口函数1)、TUMBLE滚动窗口示例2)、HOP滑动窗口示例3)、CUMULATE累积窗口示例2、GROUPINGSETS分组集介绍及示例1)、ROLLUP介绍及示例2)、CUBE介绍及示例3、SelectingGroupWindowStartandEndTimestamps4、Cas......
  • 27、Flink 的SQL之SELECT (窗口函数)介绍及详细示例(3)
    文章目录Flink系列文章一、Windowingtable-valuedfunctions(WindowingTVFs)1、TUMBLE滚动窗口1)、示例1-使用滚动窗口查询、统计(表不含主键)2)、示例2-使用滚动窗口查询、统计(表含主键)3)、官方示例-使用滚动窗口查询、统计(未验证)2、HOP滑动窗口1)、示例1-使用滑动窗口查询、统计2)......
  • Mysql查询不区分大小写
    当使用mysql查询时,发现不区分大小写。经查,是以下问题utf8_general_ci --不区分大小写utf8_bin--区分大小写  解决方法一:修改排序规则为utf8_bin 解决方法二:在查询的字段前面加个binary ......
  • 数据库的三范式是什么?MySQL数据库引擎有哪些?InnoDB与MyISAM的区别
    一、数据库的三范式第一范式:列不可再分第二范式:主键约束,行可以唯一区分第三范式:外键约束,表的非主属性不能依赖于其它表的非主属性第二范式建立在第一范式上,第三范式建立在第一第二范式上。二、MySQL数据库引擎有哪些可以用如下命令查看mysql提供的所有引擎:mysql>showengines;MySq......
  • mysql 获取当前日期周几
    --方法一:使用WEEKDAY函数SELECTWEEKDAY(CURDATE());--返回0到6,分别代表星期日到星期六--方法二:使用DAYOFWEEK函数SELECTDAYOFWEEK(CURDATE());--返回1到7,分别代表星期日到星期六--方法三:使用DATE_FORMAT函数SELECTDATE_FORMAT(CURDATE(),'%w');......
  • 在sqlserver2008中使用自带的消息队列Service Broker
    以前有个业务操作本来是用sqlserver的表中触发器来处理的,后来在使用一个存储过程中,涉及到这个表后,发现存储过程执行过程,需要等待涉及的表的触发器操作完成才会返回,导致这个存储过程耗时有点久,这样就出现锁的问题,本来想改造下代码写到C#中,后来也懒得弄了,就找了找,发现可以用消息队......
  • 【Mysql主从复制】1主多从
    这里使用docker进行演示两台mysql主从搭建1:使用Docker启动俩个Mysql容器,配置挂载数据与配置文件传送门:https://www.cnblogs.com/wanghong1994/p/17731143.html创建完后应该就有俩个Mysql(或者你有两个服务器,启动了mysql并且配置完成):[root@VM-12-9-centos/]#dockerp......
  • MySQL进阶篇:第二章_二.二_索引结构
    2.2索引结构2.2.1概述MySQL的索引是在存储引擎层实现的,不同的存储引擎有不同的索引结构,主要包含以下几种:索引结构描述B+Tree索引最常见的索引类型,大部分引擎都支持B+树索引Hash索引底层数据结构是用哈希表实现的,只有精确匹配索引列的查询才有效,不支持范......