数据库中索引架构有多重要?

2 篇文章 0 订阅

了解数据库索引是做什么的

欢迎阅读我的博客,好久没写博客了,最近在研究一些新奇的玩意。
因为公司业务数据量达到了千万级,为了解决高并发以及数据库延迟,特意把我最近的经验分享出来。

MYSQL索引介绍

MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。

打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车。

拿汉语字典的目录页(索引)打比方,我们可以按拼音、笔画、偏旁部首等排序的目录(索引)快速查找到需要的字。

索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索引包含多个列。

创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。

实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。

上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。

建立索引会占用磁盘空间的索引文件。

索引架构原理

1、定义

索引是一种数据结果,帮助提高获取数据的速度

为了提高查找速度,有很多查询优化算法。但是每种查找算法都只能应用于特定数据结构之上。

索引就是数据库创建的满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据

2、索引数据结构

目前大部分数据库系统及文件系统都采用B Tree或其变种B+Tree作为索引结构

相关概念介绍

  • B-树(B树):多路搜索树,每个结点存储M/2到M个关键字,非叶子结点存储指向关键字范围的子结点;所有关键字在整颗树中出现,且只出现一次,非叶子结点可以命中;
  • B+树:在B-树基础上,为叶子结点增加链表指针,所有关键字都在叶子结点中出现,非叶子结点作为叶子结点的索引;B+树总是到叶子结点才命中;
  • B*树:在B+树基础上,为非叶子结点也增加链表指针,将结点的最低利用率从1/2提高到2/3;

3、为什么使用B Tree(B+Tree)

红黑树也可用来实现索引,但是文件系统及数据库系统普遍采用B/+Tree,为什么?

一般来说,索引本身也很大,不可能全存内存,往往以索引文件的形式存在磁盘

  1. 单节点能存储更多数据,使得磁盘IO次数更少。
  2. 叶子节点形成有序链表,便于执行范围操作。
  3. 聚集索引中,叶子节点的data直接包含数据;非聚集索引中,叶子节点存储数据地址的指针。

4、索引分类

1.普通索引index :加速查找

2.唯一索引

主键索引:primary key :加速查找+约束(不为空且唯一)

唯一索引:unique:加速查找+约束(唯一)

3.联合索引

-primary key(id,name):联合主键索引

-unique(id,name):联合唯一索引

-index(id,name):联合普通索引

5、聚集索引和非聚集索引

聚集索引和非聚集索引使用的都是B+树结构。

1、非聚集索引
非聚集索引的叶子节点为索引节点,但是有一个指针指向数据节点。

MyISAM是非聚集索引。

2、聚集索引
聚集索引叶子节点就是数据节点。

关于聚集索引,innodb会按照如下规则进行处理:
  1,如果一个主键被定义了,那么这个主键就是作为聚集索引
  2,如果没有主键被定义,那么该表的第一个唯一非空索引被作为聚集索引
  3,如果没有主键也没有合适的唯一索引,那么innodb内部会生成一个隐藏的主键作为聚集索引,这个隐藏的主键是一个6个字节的列,改列的值会随着数据的插入自增。

innodb的普通索引,唯一索引,联合索引都是辅助索引,采用非聚集索引结构。InnoDB的所有辅助索引都引用主键作为data域。

聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。

如何高效的运用索引

这两天做了一个测试。测试MYSQL在一千万条数据下的效率
测试环境
php7.3
mysql5.6
tp6(因为插入数据比较方便)
测试结果
在进行查询一个没有建立索引的字段上进行查询

SELECT * FROM `ber_system_cs` WHERE `number` = 10000000 LIMIT 1

在这里插入图片描述
可以看到,查询竟有4秒

那么我们查询一个有索引的字段呢?

SELECT * FROM `ber_system_cs` WHERE `id` = 10000000 LIMIT 1

在这里插入图片描述
这样一对比,是不是发现差别简直不要太大

合理创建索引

mysql中索引其实就是一张隐形的数据表,而且每次查询添加以及保存,都会影响到索引,并且占用磁盘I/O

那么我们应该怎么去高效简单的解决呢?
这里我就不贴出相关技术代码了

首先,我们在自己的业务中,需要了解哪些字段是最常用,而且最需要。

比如我们平常看见的ID键,但通常都会加入自增,并且进行索引。
那么有些业务需求他不能靠ID怎么办?那从所有字段中选一个唯一的字段进行索引

平常中小型业务中,一张表中只需要索引4个字段左右即可

一旦索引多了,还是会出现明显的查询延迟,毕竟他原理就是从所有索引里查询那个关键词

关于索引的重要程度

一般都是给ID一个索引就够了,但实际业务中,查询条件都会有多个,以保证查询结果。

但是这给数据库造成很大的难题,就参考我上面的一千万条数据测试,你会发现,4秒其实在平常业务中,是个很严重的延迟。

因为考虑到业务的加载以及进程和页面渲染,同时多个用户查询,有可能会造成数据库奔溃或者服务器宕机。

不难知道,这个重要程度,在我的项目经历中,那次千万的数据,差点让我奔溃,我一共3、4年的经验还没遇到过这种问题

那时候是手忙脚乱,直到认识一个架构师,帮我解决了数据库架构,并且给我重新设计了代码架构,才解决问题。

可见架构是有多重要,我们还是得多学习学习。

结尾

1


  1. 如果还有什么想法可以在评论区进行反馈哦交流哦
    因为文章写的有点急,所有没有过多的详细,欢迎交流。 ↩︎

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Joshua Burgin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值