首页 > 数据库 >《mysql高性能》系列3:创建合适的索引

《mysql高性能》系列3:创建合适的索引

时间:2023-05-19 23:37:04浏览次数:48  
标签:name 聚簇 叶子 索引 高性能 mysql 数据 主键

1 概述

索引可以认为是存储引擎建立的一种数据结构,用来快速的根据查询条件来找到所需要的数据。由于数据一般存放在磁盘中,每次访问磁盘的时间都会比较长,因此,为了减少对磁盘的访问次数,存储引擎一般使用B-树结构来保存索引。
索引可以减少服务器层需要扫描的数据量,可以帮助服务器避免排序,将随机IO变为顺序IO。

下面讲我们常见的数据B-树结构的索引。

2 B-树索引

B-树通常有如下图所示的结构。

红色部分为索引所在列的值,白色部分为指向叶子页的指针,绿色部分为叶子页中指向下一个相邻页的指针。
蓝色的箭头为指向数据的指针,不同的存储引擎的实现不一样,主键索引和非主键索引也不同。之后再说。

当我们需要查询 where key = x条件时,且x < key1, x = Val1.2。那么,就会将叶子页1从磁盘读入内存,发现x = Val1.2所对应的数据的指针。那么,就可以根据指针去读取数据了。这样,就避免了对整个表的扫描。

2.1 多列索引(或联合索引)

联合索引在创建时,key的值是多个,在节点页内部和节点页之间按照顺序排列。比如,key(name, age, department),则首先按照name排序,如果name相同,则按照age排序,最后为department。

因此,联合索引可以起作用的场景为:

  • where name = x and age = x and department = x。称为全值匹配,即所有的条件均有。
  • 匹配最左前缀。比如,where name = x 或者 where name = x and age = x。原因是,根据这个数据结构,首先是按照name排序的,那么,就可以根据name来筛选。如果跳过name,直接使用where age = x,则不能从这个数据结构中得到排序后的结果。
  • 匹配最左前缀的开头部分。比如,where name = “A%”,则可以匹配所有名字以A开头的。
  • 匹配最左前缀的范围值。比如,名字在A%和B%之间的。

2.2 聚簇索引

聚簇索引是一种索引类型,也是一种数据存储方式,它将索引和数据存储在一起,结构如下图所示。它的数据行实际上存放在叶子页中。“聚簇”的意思就是,将数据行和相邻的键值紧凑的存放在一起。因为无法将数据行同时存放在两个索引数据结构中,因此,一个表只会有一个聚簇索引。一般而言,InnoDB会将主键索引当做聚簇索引,也就是说,该索引的数据结构中,键值为主键的值。聚簇索引的优点有:

  • 数据是按照主键大小顺序排列的。因此,根据主键查找范围值时,速度会比较快,可能某个范围的值都在一个页中。
  • 如果走聚簇索引,速度会很快,因为读索引时就可以读到数据了。但是,这也是在走主键索引的情况下(一般主键索引才是聚簇索引)。

缺点如下:

  • 如果数据全都存放在内容中,则聚簇索引的优势就没有了。
  • 插入速度依赖于插入顺序。比如,如果id使用聚簇索引,已经插入的记录为id = 1, id = 3,叶子页规定最大为2,前面两个已经成为一个叶子页了,这时候再插入id = 2,那么,前面的叶子页就得分裂,让id = 1, id = 2成为新的叶子页。因为,得保证按照主键的顺序排列数据。

2.3 InnoDB的索引方式和MyISAM的索引方式的对比

InnoDB的索引方式

主键索引:聚簇索引
二级索引(除主键之外其他列的索引存储方式):实际保存的是主键值,之后还要根据主键索引去查询

MyISAM的索引方式

主键索引:非聚簇索引,直接保存的是行的物理地址
二级索引:与主键相同,保存的也是行的物理地址

下面通过一个例子来解释这些索引方式的区别。

假设需要存储的数据的表结构为:

需要插入的数据为:主键(使用主键索引)取值为1到10000,按照随机顺序插入;列col2(使用二级索引)的值从1到1000之间的随机值。

  1. MyISAM的数据存储方式
    MyISAM按照数据插入的顺序存储在磁盘上。如下图所示。这种数据存储方式也很简单。

  2. MyISAM的主键索引和二级索引
    MyISAM的主键索引和二级索引,key是被索引的列,叶子页保存的是行的物理地址。
    主键索引结构如下:叶子页中保存的是key值(列值)和行的物理地址。叶子页内部和叶子页之间,也是按照col1(主键)的列值进行排序的。
    二级索引结构如下:

    叶子页中保存的也是key值(列值)和行的物理地址,这与主键索引相同。叶子页内部和叶子页之间,按照col2的列值进行排序。

  3. InnoDB的主键索引
    InnoDB的主键索引使用的聚簇索引,因此,数据存储方式不同于MyISAM,结构如下:叶子页保存的就是需要存储的数据。TID是事务ID,RP为回滚指针,这两者都是与事务有关的,这里不做讨论。这里的数据行的存放方式,是按照主键大小的顺序排序的。(注意,MyISAM是按照插入顺序来排列的)因此,如果InnoDB的数据插入方式不是按照主键的顺序插入的,InnoDB需要做额外的工作来是数据有序。
    因此,在使用InnoDB时,应该尽可能的按照主键顺序插入数据,并且尽可能的使用单调增加的主键来插入新行,避免页分裂操作。

  4. InnoDB的二级索引
    InnoDB的二级索引的叶子页保存的是列值(key值)和主键值。在根据二级索引查询时,先找到主键值,然后再走主键索引,去查询数据。优点:当出现行移动物理位置或者页分裂时,减少了叶子页的维护工作。因为保存的是主键值,不是物理地址。
    缺点:根据二级索引查询时,需要再走主键索引,才可以查询到数据。即需要两次查询。(但是,如果需要查询的数据只有主键,则省去了第二步的主键索引的查询。这是覆盖索引的情况,通过这个索引,就可以拿到所需要的数据了。)

2.4 覆盖索引

当可以通过索引就可以获取到数据时,就不需要读取数据行了。这样的索引,就是覆盖索引。如果一个索引包含所有需要查询的字段的值,就称之为覆盖索引。需要考虑两方面:1)要查询哪些字段;2)被索引的是哪些列。

2.5 使用索引来避免排序

因为索引是按照顺序来存储key值的,因此,对于一些排序操作,就可以利用索引来获取想要排序的结果。

4 总结

在选择索引和查询时,应该记住三个原则:

  • 单行访问是很慢的,特别是在机械硬盘存储中,从存储中读取一个数据块获得其中一个行(全表扫描),这是很慢的。使用索引,可以创建位置引用,就可以提升访问的效率了。
  • 按顺序访问范围数据是很快的。原因之一为顺序IO不需要多次磁盘寻道,之二为能够顺序读取数据,那么,就不需要额外的排序操作了。
  • 覆盖索引查询是很快的,可以直接从索引拿到数据,不需要读取数据文件了。

标签:name,聚簇,叶子,索引,高性能,mysql,数据,主键
From: https://www.cnblogs.com/phenixlife/p/17416587.html

相关文章

  • 《mysql高性能》系列4:字符集和校对
    对于字符串类型,有一个字符集的概念在里面。字符集是指,一种从二进制编码到某类字符符号的映射。例如,中文符号,在计算机底层用二进制存储,那么,就需要有一个映射表,来表示哪个中文符号用哪个二进制编码来表示。校对,是指一组用于某个字符集的排序规则。1mysql如何使用字符集只有基于字......
  • Solr搜索引擎的简介
     Solr是一个基于Lucene的搜索引擎,它能够快速、可靠、强大地处理大量数据。Solr提供了一个HTTP接口,可以通过Java、Python、PHP等多种编程语言进行访问。Solr是一个开源的项目,由Apache软件基金会维护。Solr的主要特点包括:快速:Solr使用Lucene的索引技术,能够快速地处理大量的数据......
  • Solr搜索引擎的简介
     Solr是一个基于Lucene的搜索引擎,它能够快速、可靠、强大地处理大量数据。Solr提供了一个HTTP接口,可以通过Java、Python、PHP等多种编程语言进行访问。Solr是一个开源的项目,由Apache软件基金会维护。Solr的主要特点包括:快速:Solr使用Lucene的索引技术,能够快速地处理大量的数据......
  • MySQL下载安装(Linux)
    Linux安装MySQL在线安装yum-yinstallmysql-server用Xshell,输入安装命令后,回车。源码安装下载源码进行编译安装、繁琐......
  • MySQL下载安装
    下载MySQL安装包登录MySQL官网:MySQL点击DOWNLOADS点击MySQLCommunity(GPL)Downloads点击MySQLCommunityServer点击Archives,选择需要的版本5.5版本及以下一般有MSI和ZIP两种。也可以下载5.7稳定版MySQLMSI版本是一种安装包,是一种微软安装程序,它支持一键安装,可......
  • MySQL
    数据库三大范式什么是范式?范式是数据库设计时遵循的一种规范,不同的规范要求遵循不同的范式。最常用的三大范式第一范式(1NF):属性不可分割,即每个属性都是不可分割的原子项。(实体的属性即表中的列)第二范式(2NF):满足第一范式;且不存在部分依赖,即非主属性必须完全依赖于主属性。......
  • Mysql重置主键id顺序
     消除因删除而产生错乱的主键id顺序altertable  表名  dropcolumnid;altertable  表名  addidmediumint(8)notnullprimarykeyauto_incrementfirst;  ......
  • 河北王校长MySQL
    河北王校长MySQL索引b+树数据结构\数量级\存储内容b+树优势、对比哈希表\数组\b树\跳表跳表不适用磁盘存储介质、指针管理难以适应联合索引、出现时间晚hash不支持最左前缀和范围查找数组成本过高b树树型过高,io多最左前缀原则索引覆盖索引下推扩充showindex命......
  • jsp页面连接mysql数据库报错“com.mysql.jdbc.Driver”
    今天在做web实验的时候数据库突然连不上了以下是报错我用的mysql包为mysql-connector-java:5.1.47找了好久后来在一篇博客的启发下,那篇博客中说把一般包为web下lib目录中后来我仔细观察,发现我添加的包在WEBINF目录下的classes下的lib中,难怪找不到我把它移动到外面就可以了......
  • mysql按顺序递增(出现不连续问题)
    问题在表中添加新记录时,自动递增不连续(之前出现过了473,之后删除473,再插入新纪录,新纪录的id是474,我想让他的id为8)(用springboot+mybatis-plus插入新纪录)解决第一步1.如果是InnoDB引擎:将该字段先取消“自动递增”,去掉“不是null”的对勾,取消“主键”,并保存。如下图设置:第二......