mysql 索引

1、为什么使用索引

索引是存储引擎用于快速找到数据记录的一种数据结构,好比一本教科书的目录部分,通过目录中找到对应文章的页码,便可快速定位到需要的文章。MySQL也是一样的道理,进行数据查找时,首先查看查询条件是否命中某条索引,符合则通过索引查找 相关数据,如果不符合则需要全表扫描 ,即需要一条一条地查找记录,知道找到与条件符合的记录。

数据库没有索引的情况下,数据分布在硬盘不同的位置上面,读取数据时,摆臂需要前后摆动查找数据,操作非常消耗时间。如果数据顺序摆放,那么也需要从1到6行按顺序读取,相当于进行6次IO操作,依旧非常耗时。 如果我们不借助任何索引结构1帮助我们快速定位数据的话,我们查找col2=89这条记录,就要逐行去查找、去比较。从col2=34开始,进行比较,发现不是,继续下一行。我们当前的表只有不到10行数据,但如果表很大的话,有上千万条数据,就意味着要做很多很多次磁盘I/O才能找到。现在要查找col2=89这条记录,cpu必须先去磁盘查找这条记录,找到之后加载到内存,再对数据进行处理。这个过程最耗时间的就是磁盘IO(涉及到磁盘的旋转时间(速度较快)+磁头的寻道时间(速度慢+费时))。

假如给数据使用二叉树 这样的数据结构进行存储,如下图所示:

对字段col2添加索引,相当于在硬盘上为col2维护了一个索引的数据结构,即二叉搜索树 。二叉搜索树的每个结点存储的是**(K,V)结构**,key是col2,value是该key所在行的文件指针(地址)。比如:该二叉搜索树的根节点就是(34,0x07)。现在对col2添加了索引,这时再去查找col2=89这条记录的时候会先去查找该二叉搜索树(二叉树的遍历查找)。读34到内存,89>34;继续右侧数据,读89到内存,89==89;找到数据返回。找到之后的根据就是当前结点的value快速定位到要查找的记录对应的地址。我们可以发现,只需要查找两次就可以定位到记录的地址,查询速度就提高了。

建索引的目的:减少磁盘IO的次数,加快查询速率。

2、索引及其优缺点

MYSQL官方对索引的定义为:索引(Index)是帮助MySQL高速获取数据的数据结构
索引的本质 :索引是数据结构。你可以简单理解为"排好序的快速查找数据结构",满足特定查找算法。这些数据结构以某种方式指向数据,这样就可以在这些数据结构的基础上实现高级查找算法
索引是在存储引擎中实现的 ,因此每种存储引擎的索引不一定完全相同,并且每种存储引擎不一定支持所有索引类型。同时,存储引擎可以定义每个表的最大索引数最大索引长度。所有存储引擎支持每个表至少16个索引,总索引长度至少为256字节。有些存储引擎支持更多的索引数和更大的索引长度。

优点

  • 类似大学图书馆建书目索引,提高数据检索的效率,降低数据库的IO成本,这也是创建索引最主要的原因
  • 通过创建唯一索引,可以保证数据库中每一行数据的唯一性
  • 在实现数据的参考完整性方面,可以加速表和表之间的连接。对于有依赖关系的子表和父表联合查询时,可以提高查询速度
  • 在使用分组和排序子句进行数据查询时,可以显著减少查询中分组和排序的时间,降低CPU的消耗。

缺点

  • 创建索引和维护索引要耗费时间,并且随着数据量的增加,所耗费的时间也会增加
  • 索引需要占磁盘空间 ,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,存储在磁盘上,如果有大量的索引,索引文件就可能比数据文件更快达到最大文件尺寸。
  • 虽然索引大大提高了查询速度,同时也会降低更新表的速度。当对表中的数据进行增加、删除和修改的时候,索引也要动态地维护,这样就降低了数据地维护速度。

3、InnoDB中索引的推演

3.1索引之前的查找

先来看一个精准匹配的例子:

sql 复制代码
select [列名列表] FROM 表名 WHERE 列名=xxx;

(1)在一个页中的查找

假设目前表中的记录比较少,所有的记录都可以被存放到一个页中,在查找记录的时候可以根据搜索条件的不同分为两种情况:

  • 以主键为搜索条件
    可以在页目录中使用二分法快速定位到对应的槽,然后再遍历该槽对应分组中的记录即可快速找到指定的记录
  • 以其他列作为搜索条件
    因为在数据页中并没有对非主键列建立所谓的页目录,所以我们无法通过二分法快速定位相应的槽。这种情况下只能从最小记录 开始依次遍历单链表中的每条记录,然后对比每条记录是不是符合搜索条件。很显然,这种查找的效率是非常低的。

(2)在很多页中查找

大部分情况下我们表中存放的记录都是非常多的,需要好多的数据页来存储这些记录。在很多页中查找记录的话可以分为两个步骤:

  • 定位到记录所在的页
  • 从所在的页内中查找相应的记录

在没有索引的情况下,不论是根据主键列或者其他列的值进行查找,由于我们并不能快速的定位到记录所在的页,所以只能从第一个页 沿着双向链表 一直往下找,在每一个页中根据我们上面的查找方式去查找指定的记录。因为要遍历所有的数据页,所以这种方式显然是超级耗时 的。如果一个表有一亿条记录呢?此时索引应运而生。

3.2设计索引

建一个表:

sql 复制代码
CREATE TABLE index_demo(
	c1 INT,
	c2 INT,
	C3 CHAR(1),
	PRIMARY KEY(C1)
)ROW_FORMAT=Compact;




(1)一个简单的索引设计方案







4、InnoDB中的索引方案











5、常见索引概念













相关推荐
Azoner1 分钟前
postgresql安装部署(linux)
数据库·postgresql
PyAIGCMaster26 分钟前
文本模式下成功。ubuntu P104成功。
服务器·数据库·ubuntu
drebander38 分钟前
MySQL 查询优化案例分享
数据库·mysql
初晴~1 小时前
【Redis分布式锁】高并发场景下秒杀业务的实现思路(集群模式)
java·数据库·redis·分布式·后端·spring·
盖世英雄酱581361 小时前
InnoDB 的页分裂和页合并
数据库·后端
YashanDB3 小时前
【YashanDB知识库】XMLAGG方法的兼容
数据库·yashandb·崖山数据库
独行soc3 小时前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍11基于XML的SQL注入(XML-Based SQL Injection)
数据库·安全·web安全·漏洞挖掘·sql注入·hw·xml注入
小林coding3 小时前
阿里云 Java 后端一面,什么难度?
java·后端·mysql·spring·阿里云
风间琉璃""4 小时前
bugkctf 渗透测试1超详细版
数据库·web安全·网络安全·渗透测试·内网·安全工具
drebander4 小时前
SQL 实战-巧用 CASE WHEN 实现条件分组与统计
大数据·数据库·sql