前言

如果要写出优质的SQL语句,就需要了解MySQL的存储原理。MySQL是如何分析SQL,如何利用索引查询。

Explain 关键字

explain select * from ic_base;                  --查看SQL的执行情况

id:执行编号,标识Select的执行顺序,存在子查询等负责查询的时候用来标识执行的优先顺序。

select_type: select查询语句的类型(simple,primary,subquery,derived,union,union result,dependent union,dependent subquery)。

> simple : 简单SQL

> primary : 包含union或者子查询,最外层的部分标记为primary

> subquery : 非相关子查询(子查询和主表之间有关联关系)

> derived : 派生表——该临时表是从子查询派生出来的,位于form中的子查询

> union : 包含union 或者 union all 的查询

> union result : MySQL建立的临时表需要去掉重复数据

> dependent union : 顾名思义,首先需要满足UNION的条件,及UNION中第二个以及后面的SELECT语句,同时该语句依赖外部的查询

> dependent subquery : 相关子查询(子查询和主表之间有关联关系)

> materialized :当查询优化器在执行包含子查询的语句时,选择将子查询物化之后与外层查询进行连接查询。

table:访问的表名

partitions:分区信息

type: 访问类型(system > const > eq_ref > ref > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL),innodb中不存在system.一般来说,得保证查询至少达到range级别,最好能达到ref。

> system : 这是const连接类型的一种特例,表只有一行数据

> const : 主键索引仅有一行满足条件

> eq_ref : 被驱动表和驱动表通过驱动表的主键关联。

> ref : 辅助索引访问,等值匹配或者常量匹配。

> ref_or_null : 索引访问,等值匹配或者常量匹配,存在null值。

> index_merge : 合并索引,有多个索引可以选择。

> unique_subquery : 子查询使用唯一索引

> index_subquery : 子查询使用索引

> range : 范围扫描,一个有限制的索引扫描。key列显示使用了哪个索引。当使用=、<>、>、>=、、BETWEEN 和IN 操作符,用常量比较关键字列时。

> index : 和全表扫描一样。只是扫描表的时候按照索引次序进行而不是行。主要优点就是避免了排序, 但是开销仍然非常大。

> ALL : 全表扫描

possible_keys:显示能够使用的索引

key:使用的索引

key_len:使用的索引长度(使用的索引字段长度之和,字段没有设置非空,需要加1,varchar 字段还要加2)

ref:关联列或者常数

rows:数据行数(来自统计信息)

filtered:过滤百分比,可能满足条数/总条数

Extra:MySQL的补充额外信息

> no tables used : 没有额外信息

> Using where : 当我们使用全表扫描来执行对某个表的查询,并且该语句的WHERE子句中有针对该表的搜索条件

> Using index: 当我们的查询列表以及搜索条件中只包含属于某个索引的列,也就是在可以使用索引覆盖的情况

> Impossible where: 查询语句的WHERE子句永远为FALSE时将会提示该额外信息

> Using index condition: 有些搜索条件中虽然出现了索引列,但却不能使用到索引

> no matching min/max row: 当查询列表处有MIN或者MAX聚集函数,但是并没有符合WHERE子句中的搜索条件的记录

> Using join buffer(block nested loop) : 在连接查询执行过程中,当被驱动表不能有效的利用索引加快访问速度,MySQL一般会为其分配一块名叫join

buffer的内存块来加快查询速度

> Using filesort : 很多情况下排序操作无法使用到索引,只能在内存中(记录较少的时候)或者磁盘中(记录较多的时候)进行排序,这种在内存中或者磁盘上进行排序的方式统称为文件排序(英文名:filesort)

> Using temporary : 在许多查询的执行过程中,MySQL可能会借助临时表来完成一些功能,比如去重、排序之类的,比如我们在执行许多包含DISTINCT、GROUP BY、UNION等子句的查询过程中,如果不能有效利用索引来完成查询,MySQL很有可能寻求通过建立内部的临时表来执行查询

> start temporary , end temporary: 查询优化器会优先尝试将IN子查询转换成semi-join,而semi-join又有好多种执行策略,当执行策略为DuplicateWeedout时,也就是通过建立临时表来实现为外层查询中的记录进行去重操作时,驱动表查询执行计划的Extra列将显示Start temporary提示,被驱动表查询执行计划的Extra列将显示End temporary提示

> FirstMatch(表名) : 在将In子查询转为semi-join的去重的方式(找到一条就返回)

查询优化器

set optimizer_trace="enabled=on";       --打开查询优化器

---------------需要执行的SQL(可以使用explain)-------------------------

select * from information_schema.OPTIMIZER_TRACE     --查询优化器的执行结果

set optimizer_trace="enabled=off";       --关闭查询优化器

查询优化器查询的结果

query: 对应SQL.

trace :优化过程(里面有行估算,走索引,最左前缀等一些计算成本的过程,然后MySQL自动选择一种最优方式)。

成本计算公式:全表扫描的公式: 主键索引页数*1 + 行数*0.2 = Data_length/16K + Rows*0.2 ;    主键索引页数,行数来自统计信息, 其他数据为MySQL固定常量

由于MySQL的成本计算也是估算(99%是靠谱的),但是当遇到很复杂的SQL,或者统计信息与实际情况差距太大的时候,会导致MySQL的优化过程出现问题。

这个时候我们需要干扰MySQL的执行计划,强制走我们需要的索引或者更新统计信息。

索引失效

1. 隐式转换,不走索引

表ic_website的url 创建了一个普通索引,并且该字段是varchar类型,会出现一下情况:

explain select * from ic_website where url = '123';    --  索引有效

explain select * from ic_website where url = 123;    --  索引失效

2. <>,not in 不走普通索引,主键索引还是可以走索引。

explain select * from ic_website where url <> '123';

3. 左边有% 的不走索引

explain select * from ic_website where url like '%123';

实战

一、ANALYZE TABLE  ic_base;   -- 重新收集ic_base 的统计信息,保证MySQL优化器计算准确。 查看统计信息是否被更新:select * from mysql.innodb_table_stats;

select * from mysql.innodb_index_stats;

二、hints

USE INDEX:限制索引的使用范围,们在数据表里建立了很多索引,当MySQL对索引进行选择 时,这些索引都在考虑的范围内。但有时我们希望MySQL只考虑几个索引,而不是全部的索引, 这就需要用到USE INDEX对查询语句进行设置。

IGNORE INDEX :限制不使用索引的范围

FORCE INDEX:我们希望MySQL必须要使用某一个索引(由于 MySQL在查询时只能使用一个索 引,因此只能强迫MySQL使用一个索引)。这就需要使用FORCE INDEX来完成这个功能。

hints 语法:

SELECT * FROM table1 USE|IGNORE|FORCE INDEX (col1_index,col2_index) WHERE col1=1 ANDcol2=2 AND col3=3;

三、straight_join   -- 强制改成左边为驱动表

select t1.* fromTable1 t1 STRAIGHT_JOIN Table2 t2on t1.CommonID = t2.CommonID where t1.FilterID = 1

总结

SQL优化伴随开发的全部过程,随着时间和业务的推移,一些SQL的性能跟不上了,需要重新整理和优化。

笔者遇到过好几千行的SQL(union,子查询,嵌套查询,函数,分组,排序)几乎用了SQL的全部特性,优化这类SQL第一要熟悉SQL的作用,第二点要将这类SQL拆小,先找到慢的地方,然后再考虑优化。优化SQL是一个需要耐心的活,平时一定要注意SQL写法,尽量避免一些糟糕的写法,减少后期的维护。

mysql如何explan优化sql_《MySQL数据库》MySQL 优化SQL(explain)相关推荐

  1. mysql 索引都有哪些_MySQL 数据库的优化,你知道有哪些?

    原标题:MySQL 数据库的优化,你知道有哪些? 来源 | sf.gg/a/1190000018631870 数据库优化一方面是找出系统的瓶颈,提高MySQL数据库的整体性能,而另一方面需要合理的结构 ...

  2. mysql insert 不需要日志_MySQL数据库性能优化(1)「转」

    1.MySQL概述 从本文开始我们将讨论建立在块存储方案之上的关系型数据库的性能优化方案和集群方案.关系型数据库的选型将以创业公司.互联网行业使用最广泛的MySQL数据为目标,但是MySQL的安装过程 ...

  3. mysql数据和性能平衡点_MySQL数据库性能优化(2)

    4.影响SQL性能的要素 MySQL数据库的性能不止受到性能参数和底层硬件条件的影响,在这两个条件一定的情况下,开发人员对SQL语句的优化能力更能影响MySQL数据库的性能.由于MySQL中不同数据库 ...

  4. mysql存储的判断if_if在数据库mysql存储中判断

    我们经常会对一个事物作出选择,就如屏幕前的小伙伴们选择继续浏览本篇文章,或者关闭这个界面,这就是我们所说的判断.当然看文章的判断条件是,文章的内容是否符合小伙伴们的兴趣.今天我们就数据库mysql存储 ...

  5. mysql基础小测试三_数据库---MySQL(三)

    一.视图 视图是一个虚拟表,是sql的查询结果,其内容由查询定义.同真实的表一样,视图包含一系列带有名称的列和行数据,在使用视图时动态生成.视图的数据变化会影响到基表,基表的数据变化也会影响到视图[i ...

  6. mysql 横纵表转化_数据库MySQL横纵表相互转化操作实现方法

    本文实例讲述了MySQL横纵表相互转化操作实现方法.分享给大家供大家参考,具体如下: 先创建一个成绩表(纵表) create table user_score ( name varchar(20), ...

  7. mysql被禁用了怎么办_数据库mysql存储遇到禁用怎么办?

    原标题:数据库mysql存储遇到禁用怎么办? 我们有大量数据要存放的时候,通常会需要使用数据库.不过有些功能因为本身使用的限制,想要放在数据库的时候就会出现禁用.这里我们以mysql数据库和常用的se ...

  8. mysql 迁移 nosql_小米从关系型数据库Mysql到Nosql HBase的迁移实践操作

    2013年11月22-23日,作为国内唯一专注于Hadoop技术与应用分享的大规模行业盛会,2013 Hadoop中国技术峰会(China Hadoop Summit 2013)于北京福朋喜来登集团酒 ...

  9. mysql where 条件取反_数据库MySQL之where条件查询

    数据库MySQL之where条件查询 1. where条件查询的介绍 使用where条件查询可以对表中的数据进行筛选,条件成立的记录会出现在结果集中. where语句支持的运算符: 比较运算符 逻辑运 ...

  10. mysql中编写匿名块_Oracle数据库之Oracle_PL/SQL(1) 匿名块

    本文主要向大家介绍了Oracle数据库之Oracle_PL/SQL(1) 匿名块,通过具体的内容向大家展现,希望对大家学习Oracle数据库有所帮助. 1. PL/SQL 简介 PL/SQL是一种比较 ...

最新文章

  1. 坚持使用Override 注解(36)
  2. [译]ASP.NET Core 2.0 机密配置项
  3. Leetcode 8. 字符串转换整数 (atoi) (每日一题 20210615)
  4. authenticationstring mysql_mysql5.7 的 user表的密码字段从 password 变成了 authentication_string...
  5. Jerry Wang 2013年几篇比较受欢迎的SAP社区博客
  6. Spring Integration Java DSL示例–使用Jms名称空间工厂进一步简化
  7. Win32路径操作相关API
  8. linux访问有域名的ftp,Linux安装了ftp服务怎么用域名访?
  9. 组态档(configuration file)与建构档
  10. 面试官:为什么要合并 HTTP 请求?
  11. CentOS7 安装jdk8
  12. 一键修改分辨率bat_设置分辨率的批处理 | 学步园
  13. matlab求解普通函数的导数问题(diff函数的用法)
  14. mysql压缩修复数据库_压缩修复Access数据库
  15. 显示器尺寸 和 屏幕分辨率 和 有源信号分辨率 关系
  16. 踢球骨折在家day7
  17. Containerd镜像lazy-pulling「详细解读 」
  18. EIE结构与算法映射
  19. ArcGIS Enterprise部署介绍
  20. 3d量测怎么学距离_3D虚拟仿真技术提升物流设备应用能力

热门文章

  1. C# WinForm开发系列 - Excel
  2. 把Sql数据转换为业务数据的几种方法
  3. 如何解决复杂条件下的程序流的控制问题?
  4. [Python学习] 专题一.函数的基础知识
  5. Git之深入解析如何通过GPG签署和验证工作
  6. iOS经典面试题之“runtime是如何实现weak变量的自动置nil”
  7. iOS开发之本地通知UILocalNotification
  8. 解决安装ROS 时rosdep update 问题(time out)
  9. 【C++】 C++标准模板库(一) Vector
  10. curl取跳转地址 php_PHP使用CURL获取302跳转后的地址实例