原标题:MySQL高效索引:覆盖索引

作者:踏雪无痕

cnblogs.com/chenpingzhao/p/4776981.html

概念

如果索引包含所有满足查询需要的数据,则该索引称为覆盖索引(Covering Index),也就是平时所说的不需要回表操作。

判断标准

使用explain,可以通过输出的extra列来判断,对于一个索引覆盖查询,显示为using index,MySQL查询优化器在执行查询前会决定是否有索引覆盖查询

注意

1、覆盖索引也并不适用于任意的索引类型,索引必须存储列的值

2、Hash 和full-text索引不存储值,因此MySQL只能使用B-TREE

3、并且不同的存储引擎实现覆盖索引都是不同的

4、并不是所有的存储引擎都支持它们

5、如果要使用覆盖索引,一定要注意SELECT 列表值取出需要的列,不可以是SELECT *,因为如果将所有字段一起做索引会导致索引文件过大,查询性能下降,不能为了利用覆盖索引而这么做

InnoDB

1、覆盖索引查询时除了索引本身的包含的列,还可以使用其默认的聚集索引列

2、这跟INNOB的索引结构有关系,主索引是B+树索引存储,也即我们所说的数据行即索引,索引即数据

3、对于INNODB的辅助索引,它的叶子节点存储的是索引值和指向主键索引的位置,然后需要通过主键在查询表的字段值,所以辅助索引存储了主键的值

4、覆盖索引也可以用上INNODB 默认的聚集索引

5、innodb引擎的所有储存了主键ID,事务ID,回滚指针,非主键ID,他的查询就会是非主键ID也可覆盖来取得主键ID

覆盖索引是一种非常强大的工具,能大大提高查询性能,只需要读取索引而不用读取数据有以下一些优点

1、索引项通常比记录要小,所以MySQL访问更少的数据

2、索引都按值的大小顺序存储,相对于随机访问记录,需要更少的I/O

3、大多数据引擎能更好的缓存索引,比如MyISAM只缓存索引

4、覆盖索引对于InnoDB表尤其有用,因为InnoDB使用聚集索引组织数据,如果二级索引中包含查询所需的数据,就不再需要在聚集索引中查找了

在sakila的inventory表中,有一个组合索引(store_id,film_id),对于只需要访问这两列的查 询,MySQL就可以使用索引,如下

表结构

CREATETABLE`inventory`(

`inventory_id`mediumint( 8) unsignedNOTNULLAUTO_INCREMENT,

`film_id`smallint( 5) unsignedNOTNULL,

`store_id`tinyint( 3) unsignedNOTNULL,

`last_update`timestampNOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP,

PRIMARY KEY( `inventory_id`),

KEY`idx_fk_film_id`( `film_id`),

KEY`idx_store_id_film_id`( `store_id`, `film_id`),

CONSTRAINT`fk_inventory_film`FOREIGN KEY( `film_id`) REFERENCES`film`( `film_id`) ONUPDATECASCADE,

CONSTRAINT`fk_inventory_store`FOREIGN KEY( `store_id`) REFERENCES`store`( `store_id`) ONUPDATECASCADE

) ENGINE= InnoDBAUTO_INCREMENT= 4582DEFAULTCHARSET=utf8 |

查询语句

mysql> EXPLAINSELECTstore_id, film_id FROMsakila.inventoryG

*************************** 1.row***************************

id: 1

select_type: SIMPLE

table: inventory

type: index

possible_keys: NULL

key: idx_store_id_film_id

key_len: 3

ref: NULL

rows: 4581

Extra: Usingindex

1rowinset( 0.03sec)

在大多数引擎中,只有当查询语句所访问的列是索引的一部分时,索引才会覆盖。但是,InnoDB不限于此,InnoDB的二级索引在叶子节点中存储了 primary key的值。

因此,sakila.actor表使用InnoDB,而且对于是last_name上有索引,所以,索引能覆盖那些访问actor_id的查 询,如下

mysql> EXPLAINSELECTactor_id, last_name FROMsakila.actor WHERElast_name = 'HOPPER'G

*************************** 1.row***************************

id: 1

select_type: SIMPLE

table: actor

type: ref

possible_keys: idx_actor_last_name

key: idx_actor_last_name

key_len: 137

ref: const

rows: 2

Extra: Usingwhere; Using index

1 row in set( 0.00sec)

使用索引进行排序

MySQL中,有两种方式生成有序结果集:一是使用filesort,二是按索引顺序扫描

利用索引进行排序操作是非常快的,而且可以利用同一索引同时进 行查找和排序操作。当索引的顺序与ORDER BY中的列顺序相同且所有的列是同一方向(全部升序或者全部降序)时,可以使用索引来排序,如果查询是连接多个表,仅当ORDER BY中的所有列都是第一个表的列时才会使用索引,其它情况都会使用filesort

CREATETABLE`actor`(

`actor_id`int( 10) unsignedNOTNULLAUTO_INCREMENT,

`name`varchar( 16) NOTNULLDEFAULT'',

`password`varchar( 16) NOTNULLDEFAULT'',

PRIMARY KEY( `actor_id`),

KEY`name`( `name`)

) ENGINE= InnoDBDEFAULTCHARSET=utf8 ;

insertintoactor( name, password) values( 'cat01', '1234567'),( 'cat02', '1234567'),( 'ddddd', '1234567'),( 'aaaaa', '1234567');

1、explain select actor_id from actor order by actor_id G

mysql> explainselectactor_id fromactor orderbyactor_id G

*************************** 1.row***************************

id: 1

select_type: SIMPLE

table: actor

type: index

possible_keys: NULL

key: PRIMARY

key_len: 4

ref: NULL

rows: 4

Extra: Usingindex

1rowinset( 0.00sec)

2、explain select actor_id from actor order by password G

mysql> explainselectactor_id fromactor orderbypasswordG

*************************** 1.row***************************

id: 1

select_type: SIMPLE

table: actor

type: ALL

possible_keys: NULL

key: NULL

key_len: NULL

ref: NULL

rows: 4

Extra: Usingfilesort

1rowinset( 0.00sec)

3、explain select actor_id from actor order by name G

mysql> explainselectactor_id fromactor orderbynameG

*************************** 1.row***************************

id: 1

select_type: SIMPLE

table: actor

type: index

possible_keys: NULL

key: name

key_len: 50

ref: NULL

rows: 4

Extra: Usingindex

1rowinset( 0.00sec)

当MySQL不能使用索引进行排序时,就会利用自己的排序算法(快速排序算法)在内存(sort buffer)中对数据进行排序,如果内存装载不下,它会将磁盘上的数据进行分块,再对各个数据块进行排序,然后将各个块合并成有序的结果集(实际上就是外排序)

对于filesort,MySQL有两种排序算法

1、两遍扫描算法(Two passes)

实现方式是先将需要排序的字段和可以直接定位到相关行数据的指针信息取出,然后在设定的内存(通过参数sort_buffer_size设定)中进行排序,完成排序之后再次通过行指针信息取出所需的Columns

注:该算法是4.1之前采用的算法,它需要两次访问数据,尤其是第二次读取操作会导致大量的随机I/O操作。另一方面,内存开销较小

2、 一次扫描算法(single pass)

该算法一次性将所需的Columns全部取出,在内存中排序后直接将结果输出

注:从 MySQL 4.1 版本开始使用该算法。它减少了I/O的次数,效率较高,但是内存开销也较大。

如果我们将并不需要的Columns也取出来,就会极大地浪费排序过程所需要 的内存。在 MySQL 4.1 之后的版本中,可以通过设置 max_length_for_sort_data 参数来控制 MySQL 选择第一种排序算法还是第二种。

当取出的所有大字段总大小大于 max_length_for_sort_data 的设置时,MySQL 就会选择使用第一种排序算法,反之,则会选择第二种。为了尽可能地提高排序性能,我们自然更希望使用第二种排序算法,所以在 Query 中仅仅取出需要的 Columns 是非常有必要的。

当对连接操作进行排序时,如果ORDER BY仅仅引用第一个表的列,MySQL对该表进行filesort操作,然后进行连接处理,此时,EXPLAIN输出“Using filesort”;

否则,MySQL必须将查询的结果集生成一个临时表,在连接完成之后进行filesort操作,此时,EXPLAIN输出 “Using temporary;Using filesort”返回搜狐,查看更多

责任编辑:

mysql高效索引覆盖索引_MySQL高效索引:覆盖索引相关推荐

  1. mysql 聚合索引和聚簇索引_MySQL 聚簇索引 和覆盖索引

    一.聚簇索引 1.聚簇索引并不是一种单独所以,而是一种数据储存方式. InnoDB 的聚簇索引实际上在同一结构中保存了B-Tree 索引和数据行. 2.当表有聚簇索引时,它的数据行实际上存放在索引的叶 ...

  2. mysql行锁同索引键问题_mysql 锁问题 (相同索引键值或同一行或间隙锁的冲突)

    1.使用相同索引键值的冲突 由于mysql 的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但如果是使用相同的索引键,是会出现锁冲突的.设计时要注意 例如:city表city_ ...

  3. mysql数据库存储引擎和索引的描述_Mysql InnoDB引擎的索引与存储结构详解

    前言 在Oracle 和SQL Server等数据库中只有一种存储引擎,所有数据存储管理机制都是一样的. 而MySql数据库提供了多种存储引擎.用户可以根据不同的需求为数据表选择不同的存储引擎,用户也 ...

  4. mysql 建立索引的例子_mysql建立合适的索引的例子

    在mysql数据库中,其实建索引也是一门学问,一个表中,索引并不是越多越好,而是适合你的业务才最重要.那么建立索引的时候,我们应该从以下几点去考量. 1. 索引字段越小越好,像varchar(10)肯 ...

  5. mysql索引下推原理_MySQL:好好的索引,为什么要下推?

    前段时间有读者提议讲讲索引下推,这期就把这事儿安排上.多余的前言就不赘述了,我们直接开始. 列位坐好! - 思维导图 - 回表操作 对于数据库来说,只要涉及到索引,必然绕不过去回表操作.当然这也是我们 ...

  6. mysql的表是聚集索引组织表_Mysql的Innodb引擎索引总结

    索引的目的是什么? 答:数据库添加索引的目的是为了加快查询速度. 索引的的数据结构是什么? 答:(这里的B是balance)B+树来存储索引,B+树类似于二叉树. B+树是怎么查找数据的? 答:B+树 ...

  7. mysql索引优化规则_Mysql优化选择最佳索引规则

    索引的目的在于提高查询效率,其功能可类比字典,通过该索引可以查询到我们想要查询的信息,因此,选择建立好的索引十分重要,以下是为Mysql优化选择最佳索引的方法步骤: 1. 首先列出查询中所有使用的表, ...

  8. mysql中创建唯一索引的关键字_MySQL中创建唯一索引的关键字是_______ 。

    [判断题]判断零件键槽的尺寸标注是否正确.[图片] [单选题][图片] [单选题]读零件图,回答问题:1. C3表示倒角为( )度?2. C2表示倒角锥台高度为( )?[图片] [单选题]如图为套筒零 ...

  9. MySQL索引详解之索引的利弊以及高效使用

    前言 很多人对数据库索引可能都是知其然却不知其所以然,对索引没有很深入的理解,在使用过程中也一知半解,导致没有办法准确高效地使用索引,甚至存在不少误用的情况,导致使用索引反而降低了系统的性能.下面就以 ...

最新文章

  1. 计算机学院心理节活动,计算机学院成功举办 “说出你的故事” 心理交流互助活动...
  2. android 电容屏(三):驱动调试之驱动程序分析篇
  3. 1.1节 Buck Converter--降压转换器 part1
  4. error: field 'b' has imcomplete type
  5. Linux常用的20条运维命令,值得收藏!
  6. 重启crontab服务
  7. ubuntu18下pyspider的安装
  8. Volatility内存分析工具-某即时通讯软件Windows端数据库密钥的分析
  9. python max((1、2、3)*2)_【Python】python基础2(2)
  10. 如何做好高端的总结汇报PPT呢?
  11. 论文中定性分析与定量分析的写作手法
  12. 计算机怎么查文件打印记录表,打印机历史记录
  13. 华为太极magisk安装教程_怎么升级Magisk到最新19.4版本-正确刷入Magisk,获取ROOT教程...
  14. selenium鼠标操作
  15. 静态路由——手写路由表及综合实验
  16. LearnGL - 03 - DrawQuad - VBO/EBO - 理解 CW, CCW 的正背面
  17. ARM64(M1版)Mac运行MAA以及AzurLaneAutoScript自动化打明日方舟和碧蓝航线
  18. [附源码]Python计算机毕业设计Django的项目管理系统
  19. RT-1052学习笔记 - GPIO架构分析
  20. implicitly has an ‘any‘ type...以及suppressImplicitAnyIndexErrors版本错误TypeScript 5.5问题

热门文章

  1. mysql 分段执行_了解一下项目中常用的19条MySQL优化
  2. python 线程通信 会涉及到拷贝吗_Python如何实现线程间通信
  3. linux鼠标驱动程序,Linux usb子系统(一) _写一个usb鼠标驱动
  4. java拥有键值对的数据结构_Java数据结构之004--HashMap
  5. windows 启动exe程序前注入dll(c++)
  6. django命令行常见
  7. 获取当前图层所处的坐标系统(C++)(ArcObject开发)
  8. SU编程和Madagascar编程中的函数对比和区别--终端提示函数
  9. CPU的IPC调优:通过优化代码,提高每个时钟的指令数
  10. UEFI 引导与 BIOS 引导