MySQL:索引特性

news/2024/5/21 7:01:42/文章来源:https://blog.csdn.net/yourfriendyo/article/details/126575174

索引

0. 预备知识

索引是一个“物美价廉”的特性,用来提高数据库的性能。不需要改程序、调SQL、只需要正确的创建索引,查询速度就能提高成百上千倍,但查询速度的提升也带来了插入、更新、删除速度的下降。

0.1 认识磁盘

MySQL对数据进行增删查改操作时,不可能直接访问磁盘硬件的,实际上对数据库的所有操作,都是在内存中进行的,由操作系统定期将数据刷新到磁盘上。

MySQL 给用户提供存储服务,而存储的数据在磁盘这个外设当中。磁盘是计算机中的一个机械设备,相比于计算机其他电子元件磁盘效率是比较低的。在加上IO本身的特征,可以认为,如何提交效率是 MySQL 的一个重要话题。

数据库文件,本质其实就是保存在磁盘的盘片,也就是上面的一个个扇区当中。当然,数据库文件很大也很多,一定需要占据多个扇区的。

所以最基本的找到一个文件的全部,本质就是在磁盘找到所有保存文件的扇区。而我们能够定位任何一个扇区,那么便能找到所有扇区,因为查找方式是一样的。

那么如何定位扇区呢?

磁盘的每盘都是双面的,大小完全相等。那么同半径的磁道整体上便构成了一个柱面,每个盘面都有一个磁头,所以我们只需要知道磁头、磁道、扇区对应的编号,即可在磁盘上定位所要访问的扇区。

这种磁盘数据定位方式叫做 CHS。不过实际系统软件使用的并不是 CHS 而是 LBA,一种线性地址,可以想象成虚拟地址与物理地址。系统将 LBA 地址最后会转化成为 CHS,交给磁盘去进行数据读取。

操作系统和硬盘如何交互?

如果操作系统直接使用硬件提供的数据大小进行交互,那么系统的IO代码就和硬件强相关。换言之,如果硬件发生变化系统必须跟着变化,从目前来看单次lO512字节太小了,会带来效率的降低。系统读取磁盘是以块为单位的,基本单位是 4KB 。

磁盘随机访问与连续访问?

随机访问:本次和上次lO给出扇区地址不连续,这样磁头在两次IO操作之间需要比较大的寻道动作才能重新进行IO。
连续访问:本次和上次 lO 结束的扇区地址是连续的,那磁头就能很快的开始这次IO操作,这称为连续访问。

随机访问和连续访问的效率差别非常大,可以说是10倍到20倍的差距。

0.2 MySQL数据交互

而MySQL作为一款数据库软件,它有着更高的IO场景,需要提高基本的IO效率。MySQL使用16KB进行IO交互,即MySQL和磁盘进行数据交互的基本单位是16KB。这个基本数据单元在 MySQL 里叫做 page

其实是MySQL和内核使用16KB交互,内核和磁盘使用4KB交互,但我们不关心系统,假定MySQL直接和磁盘交互。

MySQL中的数据文件,是以page为单位保存在内存当中的。MySQL的数据交互,都需要通过计算找到对应的位置。后续涉及到磁盘和内存的IO的基本单位就是Page。

为了更高的效率,一定要尽可能的减少系统和磁盘IO的次数。

 

1. 索引原理

为何MySQL和磁盘进行IO交互的时候,要采用Page的方案进行交互呢?

按Page大小进行交互,整个Page会被加载到MySQL的内存池中,这里完成了一次IO。往后如果在查找,完全不需要进行磁盘IO,而是直接在内存中进行了。所以就在单Page里面,大大减少了IO的次数。

有很大概率用户一定下次找的数据就在这个Page,因为有局部性原理。往往IO效率低下的最主要矛盾不是IO单次数据量的大小,而是IO的次数。

从现在开始,我们探讨的数据全部以Page的形式保存在MySQL内部缓冲区中了,和磁盘没有任何关系。

1.1 理解Page

MySQL中任意时刻都可能存在大量的Page页存在于MySQL内部,MySQL本身一定要对Page进行管理。

//伪代码
struct Page {struct Page* next;struct Page* prev;char buffer[16kb];
};

MySQL中的数据往往都是封装成Page结构体的形式,保存在内存中,单个大小16KB。

  • 多个Page结构体之间使用前后指针构成双向链表。
  • 单个Page结构体内部多条记录也是使用链表形式存储。

**因为有主键的原因,MySQL会自动将我们插入的数据,按主键的递增顺序进行排序。**那么为什么要进行排序呢?

插入数据时排序的目的,就是优化查询的效率。首先数据得有序才能方便查找。

1.2 主键索引

单页情况

如何提高在单个Page中的查找效率呢?

线性有序的数据可以类比一本书,书的页码从前到后一次排布。而书有目录,目录表明了所在章节的页码范围,在查找指定知识点的时候,可以先从目录找到所在章节,到指定章节再线性查找到指定位置。

针对单页Page我们也可以添加“目录”,如果我们想查找指定位置数据,先找目录到大体位置在线性查找即可。这是一种以空间换时间的做法。

从目录开始查找就能一次性排除更多数据,当然这一切也是建立在数据有序的基础上。

多页情况

Page之间也是以链表的形式组织的,只能线性查找的话效率太低。如何提高在多个Page中的查找效率呢?

因为我们需要保证数据有序,再次新插入的数据不一定会被放在最后一个Page的末尾,也有可能放在中间某个Page的中间位置。

这样的单纯用链表链起来的结构也有效率问题:

  1. 如果我们需要靠后的Page,但为了线性遍历,必须要把之前的所有Page导入内存,这样会造成大量IO。
  2. 就算需要的Page已经在内存中,线性遍历多个Page的方式也是问题。

解决思路就是给多个Page也搭配上“目录”:把多个Page看作多个记录,把Page中的最小记录的键值作为Page的键值,为其标上目录

  • 创建一个Page其中记录用来存储目录项,目录项由键值和指针构成,指向其下Page最小键值的记录。
  • 页内目录管理的是记录,这种目录管理的是页。

**目录页本质也是页,普通页存储的是用户数据,目录页存储的是普通页的地址。**这样一次查找就能排除多页,效率更高。

不过我们还需要一个管理页(可能是多个)存储其下所有目录页的最小键值,用来来管理其下所有目录页。这样每次查找从顶层管理页开始,逐步向下查找,这也就是B+树模型。

所谓索引,就是在MySQL内部,将热点数据存储在Page页,再以B+树的形式将所有Page页进行组织,形成数据结构与其配套的查找算法。

  • Page分为目录页和数据页。目录页只放各个下级Page的最小键值。
  • 自顶向下找,只需要加载部分目录页到内存,即可完成算法的整个查找过程,大大减少了IO次数。

如此就解决了我们最初链表方案的两个缺陷:线性遍历和大量IO。缺点是略降增删的效率,因为插入或删除会破坏底层数据页的结构,会向上影响到目录页。

为什么选择B+树,而不是其他数据结构?

数据结构劣势
链表只能线性遍历,效率太低
二叉搜索树退化问题,可能退化成为线性结构
AVL和红黑树二叉结构,导致树整体过高过瘦。过高需要加载Page就多IO效率低,过瘦排除的数据少
Hash散列随机的算法特征决定了范围查找时效率不行,只能一个一个找
B树底层无法线性遍历,范围查找效率不高。树体存储数据导致树过高

1.3 聚簇索引和非聚簇索引

概念存储引擎解释
聚簇索引InnoDB把索引和数放在一块
非聚簇索引MyISAM把索引和数据分离,叶节点不存储数据,只存指针

MySQL除了默认会建立主键索引外,用户也有可能以其他字段建立索引,一般这种索引叫做辅助索引或者普通索引。

  • 对于MyISAM,建立普通索引和主键索引没有差别,无非就是主键不能重复,而非主键可重复。
  • 对于InnoDB,建立普通索引,叶结点也不保存数据,而保存所在记录的主键,需要回表查询。

InnoDB普通索引不存数据而存主键,原因很简单浪费空间。而MyISAM因为其不管主键索引还是普通索引只存地址。

 

2. 索引操作

2.1 创建主键索引

创建表的时候设置主键或者后期追加设置主键,都会自动创建主键索引模型。

# 方式一
create table `tb_name` (`field` datatype primary key [, ...]);
# 方式二
create table `tb_name` (`field` datatype, primary key (id));
# 方式三
alter table `tb_name` add primary key (id);

2.2 创建唯一索引

# 方式一
create table `tb_name` (`field` datatype unique key [, ...]);
# 方式二
create table `tb_name` (`field` datatype, unique(`field`));
# 方式三
alter table `tb_name` add unique key (id);

如果建表时指定唯一键,则MySQL自动为其建立唯一键索引。

2.3 创建普通索引

# 创建表时指定索引
create table `tb_name` (`field` datatype [, ...], index(`field`));
# 追加索引
alter table `tb_name` add index(`field`);
# 追加索引
create index `idx_name` on `tb_name`(`field`);

2.4 查询索引

# 1
show index from `tb_name`;
# 2
show index from `tb_name` \G

2.5 删除索引

# 删除主键索引
alter table `tb_name` drop primary key;
# 删除唯一索引
alter table user3 drop index `index_name`;
# 删除普通索引
alter table user3 drop index `index_name`;

2.6 创建全文索引

我们目前所有的索引建立都是基于一列一个字段的,而且这字段的内容都不大。假如要对大量文字作索引,会使用到全文索引。目前只有MyISAM支持全文索引,不支持中文。

待补充。

2.7 索引创建原则

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_17816.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据讲课笔记2.1 初探大数据

文章目录零、学习目标一、导入新课二、新课讲解(一)什么是大数据(二)大数据的特征1、数据体量大2、数据类型多3、处理速度快4、价值密度低(三)研究大数据的意义(四)拥抱大数据时代1、…

【数据结构初阶】第四话 —— 动态栈的基本操作

文章目录什么是栈栈的结构1. 初始化栈2. 入栈3. 出栈4. 获取栈顶元素5. 获取栈中有效元素个数6. 检测栈是否为空7. 销毁栈8. 总结接口函数贴图什么是栈 假如有⼀个⼜细⼜⻓的圆筒,圆筒⼀端封闭,另⼀端开⼝。往圆筒⾥放⼊乒乓球,先放⼊的靠近…

U盘插入自动读写/U盘插入自动复制/pythhttps://www.cnblogs.com/wawawa888/p/16749476.htmlon检测U盘的插入,以及进行自动复制文件并写入文件

U盘自动读写的小玩意 共有四种方法(我知道的方法,全是转载。转载也很不易,可望给个硬币) 方法一(vbs方法 全自动,转载自bilibili 点我跳转)文件下载链接(点我下载) 方法二(cmd方法 需手动,转载自bilibili 点我跳转)文件下载链接(点我下载) 方法三(python方法 全…

在DataFrame中根据索引值进行排序:sort_index()函数

【小白从小学Python、C、Java】 【Python-计算机等级考试二级】 【Python-数据分析】 在DataFrame中根据索引值进行排序: sort_index()函数 [太阳]选择题 对以下python代码表述有误的选项是? import numpy as np import pandas as pd data np.random.…

ElasticSearch_03_批量处理命令mget和bulk的使用

系列文章目录 文章目录系列文章目录前言一、批量处理命令mget方案1:body请求体中指定index和type方案2:url中指定index和type,body中仅指定ids方案2扩展:url中指定index和type,body中仅指定id数组二、基于bulk的增删改…

C++开发坦克大战--补充(加入传送门)--附完整代码

目录 素材整理 穿越草地 坦克穿越草地 子弹穿越草地 传送门 判定形式 生成传送门 传送坦克 关卡模式 效果展示 ​总结 完整代码 上一篇坦克大战居然意外获得了一些关注,正好最近也完善了一些功能,同时也加入了一些自己想到的新元素,主要是…

python requests cookie的获取和使用

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、cookie是什么?二、使用步骤开始代码实现会话是什么然后写入我们的账号信息使用session访问登陆账号的url获取账号的书架上的数据完整的代码补充比…

基于javaweb在线投票管理系统ssm

基于SSM的在线投票系统以XXX学院为背景,运用在校所学习的软件开发原理,采用SpringSpringMVCMyBatis技术和MySQL数据库构建一个基于B/S模式的在线投票系统。 传统的投票模式都是通过人工手动填写问卷的方式来进行,这在很大程度上会造成人力和…

1.1 Ryu 的安装部署

What is Ryu Ryu是轻量级的、开源的SDN控制器Ryu是由日本NTT公司在2012年推出其名字在日文中的意思是“Flow”和“Dragon”的意思 Ryu架构 Ryu安装 在Ubuntu上装Ryu和Mininet,CSDN上搜教程,这一部分正确做法是对着视频敲代码如果有问题去CSDN上找解决办…

滤波器基础01——滤波器的种类与特性

滤波器是一种选频装置,它能够保留某一频段的信号,将此频段之外的信号消除。以下介绍不同分类依据下滤波器的特点。 一. 模拟滤波器与数字滤波器 根据滤波器的作用对象是模拟信号还是数字信号可将滤波器分为模拟滤波器和数字滤波器。 模拟滤波器处理模…

创建并运行一个 Spring Boot 项目

创建并运行一个 Spring Boot 项目引言第一个 Spring Boot 项目1. 创建一个 spring boot 项目第一步第二步第三步第四步2. 验证第一步第二步3. 写一个 hello world第一步解析代码第二步注意事项网页创建一个 Spring Boot 项目Spring Boot 的优点引言 Spring Boot 是 Spring 框架…

升级迭代:让我的颜色控制打印工具mypycolor更聪明,参数可以任意接收颜色控制码、颜色描述英文单词的任意组合。

【点击此处跳转笔记正文】Python 官网:https://www.python.org/ Free:大咖免费“圣经”教程《 python 完全自学教程》,不仅仅是基础那么简单…… My CSDN主页、My HOT博、My Python 学习个人备忘录好文力荐、 老齐教室 自学并不是什么神秘的…

YOLOV+pytorch+win10+CPU环境配置

Step 1:下载github YOLOV3源码 链接:https://github.com/ultralytics/yolov3 Step 2:配置CPUpytorch版本环境 WinR启动cmd,在命令提示符内输入以下命令,创建一个新环境: conda create –n yolov-pytorc…

记录自学的学习路线(详细)

目录 HTML css javaScript javaScript高级 jQuery(快速过一遍) bootstrap 移动端适配 ajax ES6 Vue2vue3全家桶(vue3暂时不学,后面会解释原因) axios promise vue2结束后 Vue3 Ts 依我而言 曾经我也迷茫过,如何学习…

JWT 和 JJWT 还傻傻的分不清吗

JWTs是JSON对象的编码表示。JSON对象由零或多个名称/值对组成,其中名称为字符串,值为任意JSON值。 JWT有助于在clear(例如在URL中)发送这样的信息,可以被信任为不可读(即加密的)、不可修改的(即签名)和URL - safe(即Base64编码的)。 JSON Web Token (JWT) 作为一个开放的标准…

CPU--指令系统

1.机器的指令的一般格式:操作码字段,地址码字段; 2.数据在存储器中的存放方式:a,从任意位置开始--不浪费空间,读写控制比较复杂; :b, 从一个存储字的起始位置开始存储--读写控制简单,浪费空间;  :c,边界对准方式,按地址数字节的整数倍位置存储--结合前两者;3.寻址…

日本抢滩Web3:“樱花”如何在加密彼岸绽放

失去互联网之后,这个第三大经济体决定在Web3奋起直追。 9月22日,Astar 创始人渡边宗太在自己的博客宣布,Astar 的原生代币通过了金融厅和 JVCEA(日本加密资产交易协会)的严格审核,并将在日本本土交易所 Bit…

汉诺塔问题分治求解

汉诺塔问题 在经典汉诺塔问题中,有 3 根柱子及 n 个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子。一开始,所有盘子自上而下按升序依次套在第一根柱子上(即每一个盘子只能放在更大的盘子上面)。移动圆盘时受到以下限制: (1) 每次只能移动一个盘子; (2) 盘子只能从柱子顶端滑…

Java Web 10 JSP 10.7 MVC 模式和三层架构

Java Web 【黑马程序员新版JavaWeb基础教程,Java web从入门到企业实战完整版】 10 JSP 文章目录Java Web10 JSP10.7 MVC 模式和三层架构10.7.1 MVC 模式10.7.2 三层架构10.7.3 MVC 和 三层架构10.7 MVC 模式和三层架构 MVC 模式和三层架构是一些理论的知识&#…

基于SpringBoot视频学习系统|视频点播系统的设计与实现【Java毕业设计·安装调试·代码讲解·文档报告】

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…