mysql 快速进阶

innodb

1. 事物的基本要素

1.1、原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。

1.2、一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。

1.3、隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。

1.4、持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。

2. 事物隔离级别

未提交读(脏读、不可重复读、幻读)
提交读(不可重复读、幻读)
可重复读(行锁和间隙锁并存,支持高并发场景,间隙锁解决了幻读)
可串型化(最高级别的表锁、性能低下,不适用高并发场景)

脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。

不可重复读(Non-repeatable read):(update 操作)在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。(A、B 两个事务同时操作)

幻读(Phantom Read):(insert 操作)在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。(A、B两个事务同时操作)

3. 数据库表结构设计的三范式

1NF: 属于第一范式关系的所有属性都不可再分,即数据项不可分。
2NF: 第二范式是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。要求数据库表中的每行数据必须可以被惟一地区分。且所有的其他列都必须有且只有一个依赖主键,不能依赖联合主键。第二范式(2NF)要求实体的属性完全依赖于主关键字。
3NF: 指每一个非主属性既不部分依赖于也不传递依赖于业务主键,也就是在第二范式的基础上消除了非主键对主键的传递依赖(避免冗余)。例如,存在一个部门信息表, 其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在员 工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息 再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该 构建它,否则就会有大量的数据冗余。

4. 反范式设计

在实际开发过程中我们一般是范式与反范式结合使用,例如加入冗余数据来减少表关联,提高查询效率,将热点数据放入缓存。

4.1 范式的优点和缺点

优点:

  1. 范式化的更新操作比反范式更快更简洁。因为所有非主键字段都是唯一的,修改起来只要改一处即可
  2. 很少有多余的数据意味着检索列表数据时更少需要 DISTINCT 或者 GROUP BY 语句。在非范式化的结构中必须使用 DISTINCT 或者 GROUP BY 才能获得一份唯一的列表,但是如果是一张单独的表,很可能则只需要简单的查询这张表就行了。
  3. 范式化的表通常更小,可以更好地放在内存里,所以执行操作会更快。

缺点:
5. 范式化设计的缺点是通常需要关联查询。稍微复杂一些的查询语句在符合范式的 表上都可能需要至少一次关联,也许更多。这不但代价昂贵,也可能使一些索引策略无效。例如,范式化可能将列存放在不同的表中,而这些列如果在一个表中本可以属于同一个索引。

4.2 反范式的优点和缺点

优点:

  1. 反范式设计可以减少表的关联;
  2. 可以更好的进行索引优化;

缺点:

  1. 存在数据冗余及数据维护异常;
  2. 对数据的修改需要更多的成本;
4.3 反范式具体应用
4.3.1 复制和缓存
  1. 复制:在开发过程中我们往往为了检索速度快减少表关联查询会将一些常用的展示属性做冗余字段,这样可以减少关联查询提高检索性能。
    缓存:缓存衍生值也是有用的。如果需要显示每个用户发了多少消息,可以每次执行一个对用户发送消息进行count 的子查询来计算并显示它,也可以在 user 用户表中建一个消息发送数目的专门列,每当用户发新消息时更新这个值。
  2. 有需要时创建一张完全独立的汇总表或缓存表也是提升性能的好办法。“缓存表”来表示存储那些可以比较简单地从其他表获取(但是每次获取的速度比较慢)数据的表(例如,逻辑上冗余的数据)。而“汇总表”时,则保存的是使用 GROUP BY 语句聚合数据的表。
  3. 在使用缓存表和汇总表时,有个关键点是如何维护缓存表和汇总表中的数据, 常用的有两种方式,实时维护数据和定期重建,这个取决于应用程序,不过一般来说,缓存表用实时维护数据更多点,往往在一个事务中同时更新数据本表和缓存表,汇总表则用定期重建更多,使用定时任务对汇总表进行更新。
4.3.2 计数器
  1. 计数器表在 Web 应用中很常见。比如网站点击数、用户的朋友数、文件下 载次数等。对于高并发下的处理,首先可以创建一张独立的表存储计数器,这样 可使计数器表小且快,并且可以使用一些更高级的技巧。
  2. 比如假设有一个计数器表,只有一行数据,记录网站的点击次数,网站的每 次点击都会导致对计数器进行更新,问题在于,对于任何想要更新这一行的事务 来说,这条记录上都有一个全局的互斥锁(mutex)。这会使得这些事务只能串行执行,会严重限制系统的并发能力。
  3. 改进办法:可以将计数器保存在多行中,每次随机选择一行进行更新。在具体实现上,可以增加一个槽(slot)字段,然后预先在这张表增加 100 行或者更多数据,当对计数器更新时,选择一个随机的槽(slot)进行更新即可。
  4. 这种解决思路其实就是写热点的分散,在JDK1.8中新的原子类 LongAdder 也是这种处理方式,而我们在实际的缓冲中间件 Redis 等的使用、架构设计中,可以采用这种写热点的分散的方式。当然架构设计中对于写热点还有削峰填谷的处理方式,这种在 MySQL 的实现中也有体现。
4.3.2 分库分表中的查询
  1. 例如,用户购买了商品,需要将交易记录保存下来,那么如果按照买家的纬度分表,则每个买家的交易记录都被保存在同一表中,我们可以很快、很方便地査到某个买家的购买情况,但是某个商品被购买的交易数据很有可能分布在多张表中,査找起来关联表较多不是很方便 。反之,按照商品维度分表,则可以很方便地査找到该商品的购买情况,但若要査找到买家的交易记录, 则相对比较复杂。

    所以常见的解决方式如下。
    ( 1 ) 在多个分片表查询后合并数据集, 这种方式的效率很低。
    ( 2 ) 记录两份数据, 一份按照买家纬度分表, 一份按照商品维度分表,
    ( 3 ) 通过搜索引擎解决, 但如果实时性要求很高, 就需要实现实时搜索

  2. 在某电商交易平台下, 可能有买家査询自己在某一时间段的订单, 也可能有 卖家査询自已在某一时间段的订单, 如果使用了分库分表方案, 则这两个需求是 难以满足的, 因此, 通用的解决方案是, 在交易生成时生成一份按照买家分片的 数据副本和一份按照卖家分片的数据副本,查询时分别满足之前的两个需求,因此, 查询的数据和交易的数据可能是分别存储的,并从不同的系统提供接口。

5. mysql 数据类型

5.1 数值类型

MySQL支持所有标准SQL数值数据类型。

这些类型包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL和NUMERIC),以及近似数值数据类型(FLOAT、REAL和DOUBLE PRECISION)。

关键字INT是INTEGER的同义词,关键字DEC是DECIMAL的同义词。

BIT数据类型保存位字段值,并且支持MyISAM、MEMORY、InnoDB和BDB表。

作为SQL标准的扩展,MySQL也支持整数类型TINYINT、MEDIUMINT和BIGINT。下面的表显示了需要的每个整数类型的存储和范围。
在这里插入图片描述

5.2 日期和时间类型

表示时间值的日期和时间类型为DATETIME、DATE、TIMESTAMP、TIME和YEAR。

每个时间类型有一个有效值范围和一个"零"值,当指定不合法的MySQL不能表示的值时使用"零"值。

TIMESTAMP类型有专有的自动更新特性,将在后面描述。
在这里插入图片描述

5.3 字符串类型

字符串类型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。该节描述了这些类型如何工作以及如何在查询中使用这些类型。

在这里插入图片描述
注意:char(n) 和 varchar(n) 中括号中 n 代表字符的个数,并不代表字节个数,比如 CHAR(30) 就可以存储 30 个字符。

CHAR 和 VARCHAR 类型类似,但它们保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。

BINARY 和 VARBINARY 类似于 CHAR 和 VARCHAR,不同的是它们包含二进制字符串而不要非二进制字符串。也就是说,它们包含字节字符串而不是字符字符串。这说明它们没有字符集,并且排序和比较基于列值字节的数值值。

BLOB 是一个二进制大对象,可以容纳可变数量的数据。有 4 种 BLOB 类型:TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB。它们区别在于可容纳存储范围不同。

有 4 种 TEXT 类型:TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。对应的这 4 种 BLOB 类型,可存储的最大长度不同,可根据实际情况选择。

5.4 MySQL数据类型选择
5.4.1 更小的通常更好

一般情况下,应该尽量使用可以正确存储数据的最小数据类型。更小的数据 类型通常更快,因为它们占用更少的磁盘、内存和 CPU 缓存,并且处理时需要 的 CPU 周期也更少。要确保没有低估需要存储的值的范围,因为在的多个地方增加数据类型 的范围是一个非常耗时和痛苦的操作。如果无法确定哪个数据类型是最好的,就选择你认为不会超过范围的最小类型。

5.4.2 简单就好

简单的数据类型的操作通常需要更少的CPU周期。例如:整型比字符操作代价要小得多,因为字符集和校对规则(排序规则)使字符比整型比较更加复杂。

5.4.3 尽量避免NULL

尽量制定列为NOT NULL,除非真的需要NULL类型的值。因为可能为NULL列使得索引失效,索引统计和值比较都更复杂。可为NULL的列会使用更多的存储空间,在MySQL里也需要特殊处理。

6. 数据库索引(以默认存储引擎innodb为基础)

6.1 B-Tree

B-tree(多路搜索树,并不是二叉的)是一种常见的数据结构。使用B-tree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度。按照翻译,B 通常认为是Balance的简称。这个数据结构一般用于数据库的索引,综合效率较高。
B-tree中,每个结点包含:
1、本结点所含关键字的个数;
2、指向父结点的指针;
3、关键字;
4、指向子结点的指针;
对于一棵m阶B-tree,每个结点至多可以拥有m个子结点。各结点的关键字和可以拥有的子结点数都有限制,规定m阶B-tree中,根结点至少有2个子结点,除非根结点为叶子节点,相应的,根结点中关键字的个数为1 - (m-1);非根结点至少有[m/2]([],向上取整)个子结点,相应的,关键字个数为[m/2]-1~m-1。
描述一颗B树时需要指定它的阶数,阶数表示此树的结点最多有多少个孩子结点(子树),一般用字母 M 表示阶数。
B-tree有以下特性:
1、关键字集合分布在整棵树中;
2、任何一个关键字出现且只出现在一个结点中;
3、搜索有可能在非叶子结点结束;
4、其搜索性能等价于在关键字全集内做一次二分查找;
5、自动层次控制;
6、所有叶子节点都在同一层
每个非终端节点包含n个关键字信息(P0,P1,…Pn, k1,…kn)
关键字的个数n满足:ceil(m/2)-1 <= n <= m-1
ki(i=1,…n)为关键字,且关键字升序排序。
Pi(i=1,…n)为指向子树根节点的指针。P(i-1)指向的子树的所有节点关键字均小于ki,但都大于k(i-1)
此处参考
https://blog.csdn.net/weixin_42300721/article/details/113423819

6.2 B+Tree
6.2.1 简介

B+树是B树的一种变形形式,B+树上的叶子结点存储关键字以及相应记录的地址,叶子结点以上各层作为索引使用。一棵m阶的B+树定义如下:
(1)每个结点至多有m个子女;
(2)除根结点外,每个结点至少有[m/2]个子女,根结点至少有两个子女;
(3)有k个子女的结点必有k个关键字。
B+树的查找与B树不同,当索引部分某个结点的关键字与所查的关键字相等时,并不停止查找,应继续沿着这个关键字左边的指针向下,一直查到该关键字所在的叶子结点为止。

6.2.2 节点结构
  1. 在 B+ 树中的节点通常被表示为一组有序的元素和子指针。如果此B+树的序数(order)是m ,则除了根之外的每个节点都包含最少 个元素最多 m-1 个元素,对于任意的节点有最多 m 个子指针。对于所有内部节点,子指针的数目总是比元素的数目多一个。因为所有叶子都在相同的高度上,节点通常不包含确定它们是叶子还是内部节点的方式。
  2. 每个内部节点的元素充当分开它的子树的分离值。例如,如果内部节点有三个子节点(或子树)则它必须有两个分离值或元素a1和a2。在最左子树中所有的值都小于等于a1,在中间子树中所有的值都在a1和a2之间((a1,a2]),而在最右子树中所有的值都大于a2。
6.2.3 特征

B+树是B树的一种变形,比B树具有更广泛的应用,m阶 B+树有如下特征:

(1)每个结点的关键字个数与孩子个数相等,所有非最下层的内层结点的关键字是对应子树上的最大关键字,最下层内部结点包含了全部关键字。
(2)除根结点以外,每个内部结点有 到m个孩子。
(3)所有叶结点在树结构的同一层,并且不含任何信息(可看成是外部结点或查找失败的结点),因此,树结构总是树高平衡的。

6.2.4 B+树与B-树

B+树是应文件系统所需而产生的一种B-树的变形树。一棵m阶的B+树和m阶的B树的差异在于:

(1)有n棵子树的结点中含有n个关键码;
(2)所有的叶子结点中包含了全部关键码的信息,及指向含有这些关键码记录的指针,且叶子结点本身依关键码的大小自小而大的顺序链接;
(3)所有的非终端结点可以看成是索引部分,结点中仅含有其子树根结点中最大(或最小)关键码。

6.3 聚集索引/聚簇索引

如果表中定义了主键,那么这个主键将被作用为聚集索引,聚集索引在逻辑上是有序的,对应物理存储也是连续的,所以查询效率要高于非聚集索引。innodb每页大小被定义为16k来保存关键字信息,所以他可以在一个节点上存储很多的关键字信息,从而减小树的高度,减少io次数,利用缓存进行快速查找。如果你没有为表定义PRIMARY KEY,MySQL拾取第一个仅有NOT NULL列的UNIQUE索引作为主键,并且InnoDB把它当作聚集索引来用。如果表中没有这样一个索引,InnoDB内部产生一个集束索引,其中用InnoDB在这样一个表内指定给行的行ID来排序行。行ID是一个6字节的域,它在新行被插入的时候单一地增加。因此被行ID排序的行是物理地按照插入顺序排的。

6.4 辅助索引/二级索引

1、辅助索引,也叫非聚集索引。和聚集索引相比,叶子节点中并不包含行记录的全部数据。叶子节点除了包含键值以外,每个叶子节点的索引行还包含了一个书签(bookmark),该书签用来告诉存储引擎可以在哪找到相应的数据行,由于innodb引擎表是索引组织表,因此innodb存储引擎的辅助索引的书签就是相应行数据的聚集索引键。
2、这里有个叫做回表的概念。通过二级索引找到主键,然后到聚集索引中找到相对应的行数据。
3、唯一索引、普通索引、前缀索引等都是二级索引。

6.5 联合索引/复合索引

多个列组合形成的唯一索引叫做联合索引,使用时按照最左前缀规则。中间不能断。

6.6 覆盖索引

即可以从辅助索引中查询到记录,不需要查询聚集索引。

6.7 自适应哈希索引

将部分热点数据建立hash索引以便下次查找时减少io操作来获取相关数据,数据库自动根据判断逻辑执行该操作。通过innodb_adaptive_hash_index参数可以关闭该功能。

6.8 全文检索之倒排索引

它是将存储于数据库中的整本书或整 篇文章中的任意内容信息查找出来的技术。它可以根据需要获得全文中有关章、 节、段、句、词等信息,也可以进行各种统计和分析。我们比较熟知的 Elasticsearch、 Solr 等就是全文检索引擎,底层都是基于 Apache Lucene 的。

小结:
1、一个索引就是一个 B+树,索引让我们的查询可以快速定位和扫描到我们 需要的数据记录上,加快查询的速度。
2、一个 select 查询语句在执行过程中一般最多能使用一个二级索引,即 使在 where 条件中用了多个二级索引。

6.9 高性能的索引创建策略

数据类型越小,查询时进行的比较操作越快。
数据类型越小,索引占用的存储空间就越少,在一个数据页内就可以放下更多的记录,从而减少磁盘IO带来的性能损耗,也就意味着可以把更多的数据页缓存在内存中,从而加快读写效率。

6.9.1 高性能的索引创建策略

1、创建索引应该选择选择性/离散性高的列。索引的选择性/离散性是指,不重复的索引值(也称为基数,cardinality)和数据表的记录总数(N)的比值,范围从1/N到1之间。索引的选择性越高则查询效率越高,因为选择性高的索引可以让MySQL在查找时过滤掉更多的行。唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。
2、很差的索引选择性就是列中的数据重复度很高,比如性别字段,不考虑政治正确的情况下,只有两者可能,男或女。那么我们在查询时,即使使用这个索引,从概率的角度来说,依然可能查出一半的数据出来。

执行计划

Column含义
id查询序号
select_type查询类型
table表名
partitions匹配的分区
type访问方法/访问类型
prossible_keys可能会选择的索引
key实际选择的索引
key_len索引的长度
ref与索引作比较的列
rows要检索的行数(估算值)
filtered查询条件过滤的行数的百分比
Extra额外信息
  1. id
    SQL查询中的序列号。id列数字越大越先执行,如果说数字一样大,那么就从上往下依次执行。
  2. select_type
    查询的类型,可以是下表的任何一种类型:
select_type类型说明
SIMPLE简单SELECT(不使用UNION或子查询的语句)
PRIMARY最外层的SELECT
UNIONUNION中第二个或之后的SELECT语句
DEPENDENT UNIONUNION中第二个或之后的SELECT语句取决于外面的查询
UNION RESULTUNION的结果
SUBQUERY子查询中的第一个SELECT
DEPENDENT SUBQUERY子查询中的第一个SELECT, 取决于外面的查询
DERIVED衍生表(FROM子句中的子查询)
MATERIALIZED物化子查询
UNCACHEABLE SUBQUERY结果集无法缓存的子查询,必须重新评估外部查询的每一行
UNCACHEABLE UNIONUNION中第二个或之后的SELECT,属于无法缓存的子查询
  1. table
    这一列表示 explain 的一行正在访问哪个表。当 from 子句中有子查询时,table列是 格式,表示当前查询依赖 id=N 的查询,于是先执行 id=N 的查询。当有 union 时,UNION RESULT 的 table 列的值为 <union1,2>,1和2表示参与 union 的 select 行id。

  2. partitions
    和分区表有关,一般情况下我们的查询语句的执行计划的 partitions 列的值 都是 NULL。

  3. type

type说明
system系统,表仅有一行(=系统表)。这是const联接类型的一个特例。
const常量,表最多有一个匹配行,因为仅有一行,在这行的列值可被优化器剩余部分认为是常数,const表很快,因为它们只读取一次。
eq_ref搜索时使用primary key 或 unique类型
ref根据索引查找一个或多个值
fulltext全文索引
ref_or_null和REF类似,可以搜索值为NULL的行
index_merge合并索引,使用多个单列索引搜索
unique_subquery唯一索引查找,替换子查询,以提高效率。
index_subquery该连接类型类似于 unique_subquery,可以替换 IN 子查询
range对索引列进行范围查找
index全索引表扫描
ALL全数据表扫描

执行效率:由快到慢依次是
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

system:
当表中只有一条记录并且该表使用的存储引擎的统计数据是精确的,比如 MyISAM、Memory,那么对该表的访问方法就是 system
const
当我们根据主键或者唯一二级索引列与常数进行等值匹配时,对单表的 访问方法就是 const。因为只匹配一行数据,所以很快。
eq_ref
在连接查询时,如果被驱动表是通过主键或者唯一二级索引列等值匹配的 方式进行访问的〈如果该主键或者唯一二级索引是联合索引的话,所有的索引列 都必须进行等值比较),则对该被驱动表的访问方法就是 eq_ref。
ref
当通过普通的二级索引列与常量进行等值匹配时来查询某个表,那么对该 表的访问方法就可能是 ref。
ref_or_null
类似ref,但是可以搜索值为NULL的行。
index_merge
一般情况下对于某个表的查询只能使用到一个索引,在某些场景下可以使用 索引合并的方式来执行查询:
unique_subquery
类似于两表连接中被驱动表的 eg_ref 访问方法,unique _subquery 是针对在一些包含IN子查询的查询语句中,如果查询优化器决定将IN子查询转换为EXISTS 子查询,而且子查询可以使用到主键进行等值匹配的话,那么该子查询执行计划 的 type 列的值就是 unique_subquery
index_subquer
index_subquery 与 unique_subquery 类似,只不过访问⼦查询中的表时使⽤ 的是普通的索引:
range
如果使用索引获取某些范围区间的记录,那么就可能使用到range访问方法, 一般就是在你的 where 语句中出现了 between、<、>、in 等的查询。
index
当我们可以使用索引覆盖,但需要扫描全部的索引记录时,该表的访问方法 就是 index。
ALL
最熟悉的全表扫描,将遍历全表以找到匹配的行

  1. possible_keys
    这一列显示查询可能使用哪些索引来查找。 在EXPLAIN 语句输出的执行计划中,possible_keys 列表示在某个查询语句中, 对某个表执行单表查询时可能用到的索引有哪些,key 列表示实际用到的索引有哪些,如果为 NULL,则没有使用索引。
  2. key
    这一列显示mysql实际采用哪个索引来优化对该表的访问。
    如果没有使用索引,则该列是 NULL。如果想强制mysql使用或忽视possible_keys列中的索引,在查询中使用 force index、ignore index。
  3. key_len
    key_len 列表示当优化器决定使用某个索引执行查询时,该索引记录的最大长度,计算方式是这样的:
    1)对于使用固定长度类型的索引列来说,它实际占用的存储空间的最大长度就 是该固定值,对于指定字符集的变长类型的索引列来说,比如某个索引列的类型 是 VARCHAR(100),使用的字符集是 utf8,那么该列实际占用的最大存储空间就 是 100 x 3 = 300 个字节。
    2)如果该索引列可以存储 NULL 值,则 key_len 比不可以存储 NULL 值时多 1 个 字节。
    3)对于变长字段来说,都会有 2 个字节的空间来存储该变长列的实际长度。
  4. ref
    当使用索引列等值匹配的条件去执行查询时,也就是在访问方法是 const、 eg_ref、ref、ref_or_null、unique_sutbquery、index_subopery 其中之一时,ref 列 展示的就是与索引列作等值匹配的是谁,比如只是一个常数或者是某个列。
  5. rows
    如果查询优化器决定使用全表扫描的方式对某个表执行查询时,执行计划的 rows 列就代表预计需要扫描的行数,如果使用索引来执行查询时,执行计划的 rows 列就代表预计扫描的索引记录行数。
  6. filtered
    查询优化器预测有多少条记录满⾜其余的搜索条件,什么意思呢?看具体的 语句:
  7. Extra
    Extra 列是用来说明一些额外信息的,我们可以通过这些额外信息来更准确的理解 MySQL 到底将如何执行给定的查询语句。MySQL 提供的额外信息很多,几十个,下面列举一些常用的

1 No tables used
当查询语句的没有 FROM 子句时将会提示该额外信息。
2 Impossible WHERE
查询语句的 WHERE 子句永远为 FALSE 时将会提示该额外信息。
3 No matching min/max row
当查询列表处有 MIN 或者 MAX 聚集函数,但是并没有符合 WHERE 子句中 的搜索条件的记录时,将会提示该额外信息。
4 Using index
当我们的查询列表以及搜索条件中只包含属于某个索引的列,也就是在可以 使用索引覆盖的情况下,在 Extra 列将会提示该额外信息。
5 Using index condition
有些搜索条件中虽然出现了索引列,但却不能使用到索引,(因为这是mysql的一个优化手段,这个改进称之为索引条件下推)如下面这个SQL:
select * from employee emp where emp .code > ‘a’ and emp .code like ‘%b’
如果在查询语句的执行过程中将要使用索引条件下推这个特性,在 Extra 列
将会显示 Using index condition,
6 Using where
当我们使用全表扫描来执行对某个表的查询,并且该语句的 WHERE 子句中 有针对该表的搜索条件时,在 Extra 列中会提示上述额外信息。
7 Using join buffer (Block Nested Loop)
在连接查询执行过程中,当被驱动表不能有效的利用索引加快访问速度, MySQL 一般会为其分配一块名叫 join buffer 的内存块来加快查询速度:
8 Not exists
当我们使用左(外)连接时,如果 WHERE 子句中包含要求被驱动表的某个 列等于 NULL 值的搜索条件,而且那个列又是不允许存储 NULL 值的,那么在该 表的执行计划的 Extra 列就会提示 Not exists 额外信息。
9 Using intersect(…)、Using union(…)和 Using sort_union(…)
如果执行计划的 Extra 列出现了 Using intersect(…)提示,说明准备使用 Intersect 索引合并的方式执行查询,括号中的…表示需要进行索引合并的索引名 称;如果出现了 Using union(…)提示,说明准备使用 Union 索引合并的方式执行 查询;出现了 Using sort_union(…)提示,说明准备使用 Sort-Union 索引合并的方 式执行查询。
10 Zero limit
当我们的 LIMIT 子句的参数为 0 时,表示压根儿不打算从表中读出任何记录, 将会提示该额外信息。
11 Using filesort
有一些情况下对结果集中的记录进行排序是可以使用到索引的
12 Using temporary
在许多查询的执行过程中,MySQL 可能会借助临时表来完成一些功能,比如 去重、排序之类的,比如我们在执行许多包含 DISTINCT、GROUP BY、UNION 等 子句的查询过程中,如果不能有效利用索引来完成查询,MySQL 很有可能寻求通 过建立内部的临时表来执行查询。如果查询中使用到了内部的临时表,在执行计 划的 Extra 列将会显示 Using temporary 提示。
13 Start temporary, End temporary
有子查询时,查询优化器会优先尝试将 IN 子查询转换成 semi-join(半连接优 化技术,本质上是把子查询上拉到父查询中,与父查询的表做 join 操作),而 semi-join 又有好多种执行策略,当执行策略为 DuplicateWeedout 时,也就是通 过建立临时表来实现为外层查询中的记录进行去重操作时,驱动表查询执行计划 的 Extra 列将显示 Start temporary 提示,被驱动表查询执行计划的 Extra 列将显 示 End temporary 提示。
14 LooseScan
在将 In 子查询转为 semi-join 时,如果采用的是 LooseScan 执行策略,则在 驱动表执行计划的 Extra 列就是显示 LooseScan 提示。
15 FirstMatch(tbl_name)
在将 In 子查询转为 semi-join 时,如果采用的是 FirstMatch 执行策略,则在 被驱动表执行计划的 Extra 列就是显示 FirstMatch(tbl_name)提示。

7. mysql 执行顺序

  1. mysql书写顺序
    (1) SELECT
    (2) DISTINCT <select_list>
    (3) FROM
    (4) <join_type> JOIN <right_talbe>
    (5) ON <join_condition>
    (6) WHERE <where_condition>
    (7) GROUP BY <group_by_list>
    (8) HAVING <having_condition>
    (9) ORDER BY <order_by_condition>
    (10) LIMIT <limit_number>
    (11) UNION
  2. mysql执行顺序
    (7) -> (8) -> (1) -> (3) -> (2) -> (4) -> (5) -> (6) -> (9) -> (10) -> (11)

1、from 对查询指定的表计算笛卡尔积
2、on 按照 join_condition 过滤数据
3、join 添加关联外部表数据
4、where 按照where_condition过滤数据
5、group by 进行分组操作
6、having 按照having_condition过滤数据
7、select 选择指定的列
8、distinct 指定列去重
9、order by 按照order_by_condition排序
10、limit 取出指定记录量
11、union 合并表数据

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值