当前位置: 首页 > news >正文

9.MySQL索引

索引意义和分类

        索引:价值在于提高一个海量数据的检索速度。查询速度的提高是以插入、更新、删除的速度为代价的(数据库引擎不仅要修改原始数据表(Table),还必须同步更新所有相关的索引结构,以保持数据和索引的一致性

索引分类:

  • 主键索引(primary key)
  • 唯一索引(unique)
  • 普通索引(index)
  • 全文索引(fulltext)--解决中文索引问题

认识磁盘

最基本的,找到一个文件的全部,本质,就是在磁盘找到所有保存文件的扇区。

磁盘:CHS定址,磁头定柱面,柱面定磁道,磁道定扇区
系统读取磁盘,是以块为单位的,基本单位是 4KB(出于效率和解耦)

随机访问 vs 连续访问

  • 随机访问:本次IO所给出的扇区地址和上次IO给出扇区地址不连续,这样的话磁头在两次IO操作之间需要作比较大的移动动作才能重新开始读/写数据。
  • 连续访问:如果当次IO给出的扇区地址与上次IO结束的扇区地址是连续的,那磁头就能很快的开始这次IO操作,这样的多个IO操作称为连续访问。
  • 因此尽管相邻的两次IO操作在同一时刻发出,但如果它们的请求的扇区地址相差很大的话也只能称为随机访问,而非连续访问。
  • 磁盘是通过机械运动进行寻址的,随机访问不需要过多的定位,故效率比较高。

总结:随机访问磁头需要大幅度移动寻址,连续访问不用,连续访问因此效率高。

理解索引设计缘由

MySQL服务器,本质是在内存中的,所有数据库的CURD操作,都是在内存中进行的!--- 索引也是如此。

提高算法效率的因素:

1)组织数据的方式 

2)算法本身

MySQL与磁盘交互基本单位

        mysql是应用层的服务,由OS体系结构可以肯定,mysql访问磁盘(硬件)必须贯穿OS,通过内核文件缓冲区进行读取数据。数据需要持久化时就调用 fsync(int fd)刷新到外设(磁盘)。

        mysql进行IO的基本单位是16KB。这个基本数据单元,在 MySQL 这里叫做page。

        mysql启动时会开辟一块缓冲区,大小默认是128MB。

建立共识

mysql数据文件,都是以page为单位保存在磁盘中的

如何让IO变高效?尽可能减少系统和磁盘IO次数(磁盘寻址很慢,数据拷贝还行 -> 减少寻址次数)

page理解

问题1:为什么向一个具有主键列表中,插入乱序主键字段值,最后按主键排序了?

        mysql自己做的,可以很方便引入目录(即使不创建主键,mysql会创建隐藏列作为主键)

为何IO交互要是 Page

        page大小16KB,一次加载大的数据,且因为有局部性原理,加载的数据往往可能下次被用到,可以减少IO次数。往往IO效率低下的最主要矛盾不是IO单次数据量的大小,而是IO的次数。

问题2:page理解

        mysql内部,一定会存在大量page,必须要管理起来 -> 先描述,在组织。

假设page就是双向链式结构,

struct page

{

        struct *page prev;

        struct *page next;

        char[NUM] buff;

}

一个page16KB,mysql通过双向链表管理在buffer-pool内部。

效率问题:

但是链式结构的查找效率太低了,如何改良?

1)给buff加上目录(每个目录项的构成是:键值+指针

这样一来,查找时就能跳着找,效率翻了2倍。但效率还是比较低,时间复杂度没有变

2)拓展一下

        这样一来,单次筛选淘汰数量变多了,查找效率变快了。而且只让最底层page存数据,那么非叶子page就可以存更多的目录。

引入数据结构,B+树(链接:4.B-树-CSDN博客

mysql innodb下的索引结构是B+树(如果建表没有指定主键,会有默认主键)
索引本质就是数据结构B+树(时间复杂度logM(N),M为目录项个数)

1.叶子节点保存有数据,路上节点没有;非叶子节点,不要数据,只要目录项。非叶子节点,由于不存数据,可以存储更多的目录项,目录页,可以管理更多的叶子page,这课树,一定是一个 “矮胖” 的树 -> 途径路上节点,减少 -> 找到目标数据只需要更少的page!IO次数更少,IO层面,提高了效率

2.叶子节点全部用链表级联起来原因

a.首先这就是B+树特点

b.我们比较希望进行范围查找(即10~20之间数据,只需找10和20确定边界,其余靠遍历O(1))

为什么其他数据结构不行?

  • AVL &&红黑树?虽然是平衡或者近似平衡,但是毕竟是二叉结构,相比较多阶B+,意味着树整体过高,大家都是自顶向下找,层高越低,意味着系统与硬盘更少的IO Page交互。
  • Hash?官方的索引实现方式中, MySQL 是支持HASH的,不过 InnoDB 和 MyISAM 并不支持.Hash跟进其算法特征,决定了虽然有时候也很快(O(1)),不过,在面对范围查找就明显不行(Hash不适合范围查找)

B树?最值得比较的是 InnoDB 为何不用B树作为底层索引?

        B树节点,既有数据,又有Page指针,而B+,只有叶子节点有数据,其他目录页,只有键值和Page指针。那么这就意味着B树树高会比B+树更高,目录项存键值会变少,IO次数变多;而且B树也不方便范围查找;因此效率没有B+树高。

聚簇索引和非聚簇索引

MyISAM是采用叶子节点数据存数据地址的方式,将key值与数据分离(非聚簇索引)。

而Innodb采用的是key与数据放一起的方式,聚簇索引。

        MySQL 除了默认会建立主键索引外,我们用户也有可能建立按照其他列信息建立的索引,一般这种索引可以叫做辅助(普通)索引。

  • 对于 MyISAM ,建立辅助(普通)索引和主键索引没有差别,无非就是主键不能重复,而非主键可重复。
  • InnoDB 的非主键索引中叶子节点并没有数据,而只有对应记录的key值(主键索引)所以通过辅助(普通)索引,找到目标记录,需要两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。这种过程,就叫做回表查询

        为何 InnoDB 针对这种辅助(普通)索引的场景,不给叶子节点也附上数据呢?原因就是太浪费空间了。

索引操作

创建主键索引:

1)建表时直接跟在属性列后面,例:id int primary key

2)建表时指定在表内末尾,例:primary key(id)

3)建表后添加:alter table 表名 add primary key(id)

主键索引的特点:

  • 一个表中,最多有一个主键索引,当然可以使符合主键
  • 主键索引的效率高(主键不可重复)
  • 创建主键索引的列,它的值不能为null,且不能重复
  • 主键索引的列基本上是int

创建唯一键索引:

1)建表时跟属性列后,例:name varchar(20) unique

2)建表时指定在表内末尾,例:unique(name)

3)建表后添加:alter table 表名 add unique(name)

唯一索引特点(唯一键):

  • 一个表中,可以有多个唯一索引
  • 查询效率高
  • 如果在某一列建立唯一索引,必须保证这列不能有重复数据
  • 如果一个唯一索引上指定not null,等价于主键索引

创建普通索引:
1)创建表时指定在表内末尾,例:index(name)

2)建表后添加,例:alter table 表名 add index(name)

3)指定索引名创建,例:create index 要创建的索引名 on 表名(name)

普通索引的特点:

  • 一个表中可以有多个普通索引,普通索引在实际开发中用的比较多
  • 如果某列需要创建索引,但是该列有重复的值,那么我们就应该使用普通索引

创建全文索引:
前提条件:表的存储引擎必须是MyISAM,默认全文索引支持英文,不支持中文。如果对中文进行全文检索,可以使用sphinx的中文版(coreseek)

创建表时指定在表内末尾:FULLTEXT (字段1,字段2,...)

特别注意:使用全文索引时,如果不指定索引,默认是不用的
查看sql语句执行方式:explain select语句

key为NULL表示没有使用到索引

使用全文索引方式:select * from 表名 where MATCH(字段1,字段2...)  AGAINST('database')   其中字段为创建全文索引时的字段

查询索引:

1)show keys from 表名

2)show index from 表名

3)desc 表名

删除索引:

1)删除主键索引:alter table 表名 drop primary key

2)删除唯一索引,普通索引,全文索引:alter table 表名 index 索引名

3)drop index 索引名 from 表名

索引创建原则

  • 比较频繁作为查询条件的字段应该创建索引
  • 唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件
  • 更新非常频繁的字段不适合作创建索引
  • 不会出现在where子句中的字段不该创建索引

复合索引:即索引指定两个及两个以上字段,这两个字段一起充当key(类比复合主键)

索引最左匹配原则:可以只给出最左字段进行查找

索引覆盖:解决非聚簇索引回表导致效率低问题

例子:user表:id (主键) ,name,age,city。

给name创建了一个索引

查询:SELECT age, city FROM users WHERE name = ‘李四’;

由于是非聚簇索引,name是普通索引,最终会拿到其对应主键id,进行回表。

回表操作是非常影响效率的,再查一次,途径路上节点需要IO。

解决方法核心:从key上直接获取数据,避免回表

        给name,age,city三个创建一个复合索引。

        这时候在以name为条件,最左匹配原则查找时,找到了,就可以直接拿到age和city,不用再进行回表了。

        大幅提升查询性能:这是最核心的优势。由于避免了耗时的回表操作(尤其是随机I/O),查询速度可以得到数量级的提升。

http://www.dtcms.com/a/458145.html

相关文章:

  • Java--多线程基础知识(四)
  • 实现接口文档与测试脚本的实时同步
  • 用vis做的简单网站汉语言专业简历制作说明
  • 如何查看网站开发语言.net core 网站开发
  • 第5章:聊天记忆(Chat Memory)—让 AI 记住上下文
  • RAG创新方案支REFRAG
  • 高通收购Arduino,加速开发者获取领先的边缘计算与AI技术
  • 住房和城市建设厅网站wordpress本地网站怎么访问
  • mongo 适应场景
  • 沧浪企业建设网站价格win8导航网站模板
  • 实战篇:智能选配合理之轨——工业远心镜头选型终极攻略
  • 深入理解队列(Queue):从原理到实践的完整指南
  • 网站开发企业组织结构集团有限公司
  • 营销型网站建设 博客网页制作怎么做第二页
  • 网站前台功能傻瓜式网站
  • 初识Redis:理解其定位与适用场景
  • 网站客户端制作教程广州抖音推广公司
  • 项目绩效改进方案
  • 【碎片化学习】工具文:计算机通用术语中常见的100个英文单词
  • 解决 VNC 远程连接无法复制粘贴的完整指南
  • 门户网站建设方案ppt刷排名seo
  • 雅特力AT32单片机的使用 , 工程建立.
  • 交易平台网站建设项目需求asp.net网站开发技术
  • 手机淘宝客网站怎么做的网页设计制作实训报告模板
  • 11.1 kubectl命令行工具
  • SSM房屋租赁管理系统d97n3(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • 不备案的网站需要注销吗优化大师 win10下载
  • 做盗链网站八大员继续教育入口
  • 长春网站建设首选网诚传媒_正规网站建设服务中心
  • 网站开发和软件开发区别怎么做宣传