索引 ---- mysql

目录

1. 索引

1.1 概念

1.2 作用

1.3 使用场景

1.4 使用

1.4.1查看索引

 1.4.2 创建索引

1.4.3 删除索引

1.5 注意事项

1.6 索引底层的数据结构 (面试经典问题)


1. 索引

1.1 概念

索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引, 并指定索引的类型,各类索引有各自的数据结构实现。

1.2 作用

  • 数据库中的表、数据、索引之间的关系,类似于书架上的图书、书籍内容和书籍目录的关系。
  • 索引所起的作用类似书籍目录,可用于快速定位、检索数据。
  • 索引对于提高数据库的性能有很大的帮助。

1.3 使用场景

要考虑对数据库表的某列或某几列创建索引,需要考虑以下几点:
  • 数据量较大,且经常对这些列进行条件查询。
  • 该数据库表的插入操作,及对这些列的修改操作频率较低。
  • 索引会占用额外的磁盘空间。
满足以上条件时,考虑对表中的这些字段创建索引,以提高查询效率。
反之,如果非条件查询列,或经常做插入、修改操作,或磁盘空间不足时,不考虑创建索引。

1.4 使用

创建主键约束( PRIMARY KEY )、唯一约束( UNIQUE )、外键约束( FOREIGN KEY )时,会自动创建对应列的索引。  

1.4.1查看索引

show index from 表名;


上述student表中, id是主键, 所以会自动创建一个索引, 所以我们可以查看索引

关于出现的一些属性,我们后续介绍

 1.4.2 创建索引

对于非主键、非唯一约束、非外键的字段,可以创建普通索引
create index 索引名 on 表名(列名);
例如: 创建班级表中name字段的索引

1.4.3 删除索引

drop index 索引名 on 表名;
例如: 删除班级表中name字段的索引

1.5 注意事项

索引的创建, 其实是一个危险的操作
如果针对空的表, 或者表中的数据不多, 此时创建索引无所谓
如果表本身很大, 此时创建索引操作, 就会引起大量的CPU/硬盘IO的消耗, 数据库可能会挂掉
  • 为什么会如此呢?
索引背后其实就是数据结构, 例如B+树, 那么创建索引的过程, 其实就是构建B+树的过程, 这个过程本身就比较复杂, 再加上数据量庞大, 就会引起巨大的消耗
  • 如何解决呢?
并不难想到, 既然数据量很大的时候, 我们不能创建索引, 那我们可以在建表初期数据量不大的时候, 就把索引加上, 未来数据量大就不怕了
  • 但是我们没办法知道未来这张表会不会变大, 如果眼下有一张很大的表,并且针对这一列没有创建索引, 我们还要频繁查询该怎么办呢?
办法就是: "李代桃僵": 部署新的数据库, 用新的数据库代替旧的数据库
  1. 另外搞一台机器, 也搭建好一样的数据库服务器
  2. 创建表, 建立索引(此时是空表)
  3. 把旧的数据库的数据, 导入到新的数据库中(非常耗时)
  4. 数据导好后, 把应用程序的请求切换到新的服务器上即可

此时, 就可以顺利加上索引, 并且数据库可不会挂掉

这种方式还有一个非常大的好处, 一旦新的服务器出现问题, 随时都可以切换回旧的服务器, 避免问题扩大化

其实, 开发中的一些"高风险操作" , 都可以通过类似的方式来完成

1.6 索引底层的数据结构 (面试经典问题)

索引, 其实就是引入了一些数据结构, 来加快查询的速度

默认情况下, 进行条件查询操作, 就是遍历表, 一条一条数据带入条件
引入索引, 就是通过其他的数据结构, 来加快查询的速度, 减少遍历表的可能

对于应用于数据库的数据结构, 我们要求即能准确查找, 又能范围查找才行

思考我们学过的能够查找的数据结构:

1)哈希表

谈到哈希表的时间复杂度, 往往不谈最坏的, 就认为是O(1)

为什么不能说哈希表的复杂度是O(N)呢?

N表示哈希表中, 所有的数据加起来是N, 那么链表的长度肯定不是N, 除非是所有数据出现在一根链表上的极端情况, 假设最多可以设链表最大长度为M,那么复杂度为O(M), 但是在使用hash表时, 是会对hash表进行扩容的, 控制链表的长度不会很长, 所以时间复杂度近似认为是O(1)

哈希表是无序的, 只能查询key相等的情况, 不能进行范围查询, 所以不能应用于数据库

2) 二叉搜索树

一个普通的二叉搜索树, 时间复杂度为O(N), 这时最坏的情况, 但是如果是较为平衡的二叉搜索树, 时间复杂度就是O(logN)

AVL树, 是一个平衡的二叉树, 时间复杂度就是O(logN)

说个题外话

为什么TreeMap/TreeSet 不适用AVL树呢? 而是使用红黑树?

红黑树本质上是一个不那么平衡的二叉搜索树(要求较宽松)

而AVL树, 是一个非常严格的平衡二叉搜索树(要求很严格)

那么当要求较为严格的时候, 随便进行一些增删改的操作, 都可能会破坏要求, 从而触发旋转, 每次旋转都是有开销的, 那么红黑树触发旋转的概率就远远低于AVL树, 虽然红黑树没有那么平衡, 但是查询的时候速度是没差多少的

二叉搜索树不应用于数据库的原因:
  • 原因一:按道理, 红黑树中的元素是有序的, 可以进行范围查询, 但是看一个例子:
想要找到22的后继元素, 需要往上一直回溯, 直到父亲节点, 才能找到后继元素, 所以未必是最好的选择
  • 原因二: 当元素非常多时, 就会使树变得比较高, 树越高, 查询的效率就越低, 而数据库的数据/索引都是保存在硬盘上的, 每一次比较, 都需要进行一次硬盘I/O操作
3) B树
B树是一个N叉搜索树, 每个节点可以存储多个元素, 延伸出多个子树, 此时表示同样数量的数据, 需要的节点就少了, 对应的高度也大大降低了

B树的优点:
  1. 每个节点上的这些key都是有序排列的, 比较时可以用二分查找, 比较高效
  2. B树也会控制, 某个节点上保存的key不会太多, 如果插入更多的元素, 使key变多了, 就会使结点分裂出更多的子树
  3. 多个数据, 都是放在一块连续的存储空间上, 进行比较的时候,一次硬盘IO就能读出整个结点, 硬盘IO读取很慢, 所以减少硬盘IO的访问次数, 可以提高效率

4)B+树

其实数据库的最终形态是B+树, 相当于是B树的升级版

  1. N叉搜索树
  2. 每个父节点中的元素都会在子节点中以最大值的方式存在
  3. 叶子结点着一层通过链表连上

根据上述规则来排列数据, 此时叶子结点这一层, 就包含了整个数据集合的全集
而且叶子结点是由类似链表的结果连接起来的, 此时就可以通过上述链式结果非常方便的遍历整个表中的所有数据, 同时也非常方便进行范围查询, 比如我们想查 id>=4 and id<9 , 就可以从根节点开始找4, 找到4在叶子结点的位置, 然后沿着链表向后就可以找到满足范围的值
B+树相比于B树的优势:
  1. 非常方便进行遍历和范围查询
  2. 当前任何一次查询操作, 最终都是要落到叶子结点完成的, 查询任何数据, 经过硬盘IO的次数都是一样的, 查询所消耗的时间是稳定的(稳定其实是个优点!)
  3. 由于叶子结点是数据的全集, 非叶子结点中, 都是重复出现的数据, 就可以把表中的每一行数据, 最终都关联到叶子结点这一层, 而非叶子结点值保存一个单纯的key值即可
    例如上面的数据, 假设代表的是学生表, 那么这些数据是学生id, 但是在叶子结点中, 存储的就是表中每一行的数据, 不单单是id

我们所看到的表格, 只是逻辑上的结构, 实际上的底层结构, 就是B+树, 就会按照主键的索引的这个B+树的叶子结点来保存每一行数据
这样组织之后, 非叶子结点占用的空间就比较小(只保存id), 此时就可以将非叶子结点缓存到内存中(当然这份数据在硬盘也保存着, 只是为了提高效率, 就把这部分结构放在内存中了), 这样查询速度就又提高了(内存的读取速度很快)
如果你的表创建了主键, 那么自然是通过你创建的主键的索引的B+树来组织的
如果你没创建主键, mysql其实生成了一个隐藏主键, 按照隐藏主键在构造B+树

举一个例更好理解:
给定一个表student(id int,name varchar(20),classId int);
  1. 如果我们没有给出主键, 那么mysql会自动生成一个隐藏主键(假设是id), 此时就会产生索引和B+树
  2. 如果我们给出主键是id, 同样也会生成索引和B+树

    针对上述表查询情况有两种:
    1) 走索引的情况
        select * from student where id = 20;
        select * from student where id>20 and id < 100;
        此时就会根据上述B+树进行查询
    2) 不走索引的情况(不根据id进行查询)
        select * from student where classId = 20;
        此时直接通过上述叶子结点的链表进行遍历, 一个一个的与条件进行比较
  3. 如果我们再根据name这一列创建索引
    此时就会构造出另一个以name为关键字的B+树, 是和上面的主键B+树独自存在的

    非主键的B+树, 叶子结点存放的是非主键的字段和对应的主键
    此时, 按照名字查询时, 先在nameB+树上查询相应的name对应的id值, 再去主键idB+树查询数据(此过程叫做"回表")

其实B+树存在的前提, 是使用了innodb这个存储引擎
mysql支持多种存储引擎, 不同的存储引擎所用的索引数据结构是不同的
innodb是最常用的, 也是面试常考的(后续介绍)

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

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

相关文章

11.3 指针和函数

11.3 指针和函数 本节必须掌握的知识点&#xff1a; 指针作为函数的参数 数组作为函数的参数 指针作为函数的返回值 在C语言中&#xff0c;指针的一个重要作用就是作为函数参数使用&#xff0c;本节将介绍这一重要作用。 11.3.1 指针作为函数的参数 实验一百一十三&#xff…

电磁兼容(EMC):BUCK变换器基本原理及传导辐射分析设计

目录 1. BUCK电路拓扑及原理 2. Buck拓扑电路电磁场分析 3.总结 开关电源替代线性电源&#xff0c;解决了效率和体积问题&#xff0c;但也带来了新的EMI问题。开关电源也是产品内部的强辐射源之一&#xff0c;基于透过现象看本质&#xff0c;将复杂问题简单化&#xff0c;本…

T检验——单样本t检验/两独立样本t检验/配对样本t检验

T检验——单样本t检验/两独立样本t检验/配对样本t检验 1.单样本t检验1.1 适用范围 2. &#xff08; 独立样本t检验&#xff09;两独立样本t检验3.ANOVA多组样本显著性检验&#xff08;2组以上&#xff09;4. 配对样本T检验 1.单样本t检验 1.1 适用范围 单样本t检验:即已知样本…

成功解决“IndexError: deque index out of range”错误的全面指南

成功解决“IndexError: deque index out collections.deque out of range”错误的全面指南 引言 在Python编程中&#xff0c;collections.deque 是一个双端队列&#xff08;double-ended queue&#xff09;&#xff0c;支持从两端快速添加和删除元素。然而&#xff0c;与列表&…

Linux网络-守护进程版字典翻译服务器

文章目录 前言一、pid_t setsid(void);二、守护进程翻译字典服务器&#xff08;守护线程版&#xff09;效果图 前言 根据上章所讲的后台进程组和session会话&#xff0c;我们知道如果可以将一个进程放入一个独立的session&#xff0c;可以一定程度上守护该进程。 一、pid_t se…

mysql(数据库)可视化工具——Navicat Premium

Navicat Premium是一款功能强大的数据库管理工具&#xff0c;它支持多种数据库管理系统&#xff0c;包括MySQL、MariaDB、SQL Server、SQLite、Oracle和PostgreSQL等。Navicat Premium提供了直观的用户界面&#xff0c;使用户能够轻松地管理数据库结构、执行复杂的SQL查询、导入…

CUDA Unity Compute Shader 3

计划 这应该是第3章的读书笔记&#xff0c;但是因为第3章读起来比较困难&#xff0c;所以先看了《CUDA并行程序设计编程指南》的第5章和第6章&#xff0c;感觉读起来顺畅多了&#xff0c;《CUDA并行程序设计编程指南》暂定精读第5、6、7章 1.如何生成ptx文件 属性->CUDA C/…

[QT] MAC使用Qt Creator运行程序如何仅运行一个进程?

大家刚开始使用QtCreator会发现每次run程序&#xff0c;都会出现一个程序进程&#xff0c;使得调试操作增加。如下&#xff0c;每次run都会出现一个demo14的进程。 如何每次run后&#xff0c;就关闭上一次的进程&#xff0c;而重新拉起新进程呢&#xff1f; 看这里 这是默认…

Redis-02

redis安装包位置 /opt/redis-7.2.5 redis默认安装路径&#xff1a; 配置文件路径&#xff1a;/usr/local/bin/redisconfig gcc安装位置 /opt/rhredis启动&#xff1a; 在/usr/local/bin目录下输入redis-server redisconfig/redis.confredis性能测试命令 redis-benchmark [opt…

【WEEK14】 【DAY5】Swagger第三部分【中文版】

2024.5.31 Friday 接上文【WEEK14】 【DAY4】Swagger第二部分【中文版】 目录 16.6.配置API分组16.6.1.修改SwaggerConfig.java16.6.2.重启 16.7.实体配置16.7.1.新建pojo文件夹16.7.2.修改HelloController.java16.7.3.重启 16.8.常用注解16.8.1.Swagger的所有注解定义在io.swa…

NIUSHOP多商户V6版预售背后的前端技术革新

随着电子商务的快速发展&#xff0c;多商户电商平台成为了市场上的热门选择。在这个背景下&#xff0c;NIUSHOP多商户V6版的预售活动引发了广泛关注。本文将从前端技术的角度&#xff0c;探讨NIUSHOP多商户V6版在预售背后所蕴含的技术革新和亮点。 一、引言 NIUSHOP多商户系统…

node.js点餐系统app-计算机毕业设计源码84406

摘 要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#xff0c;科学化的管理&#xff0c;使信息存…

php反序列化学习(3)

1、session 当session_start()被调用或者php.ini中session.auto_start为1时&#xff0c;php内部调用会话管理器&#xff0c;访问用户session被序列化后&#xff0c;存储到指定目录&#xff08;默认为/tmp&#xff09;。 漏洞产生&#xff1a;写入格式与读取格式不一致 处理器…

如何设置让背景颜色不包括 padding 部分,顺带全面学习 background-clip 属性(可以实现文字渐变)

先解决需求 实现背景颜色不包括 padding 部分&#xff0c;直接给容器添加 css 属性&#xff1a;background-clip:content-box; 示例代码&#xff1a; .content-box-example {background-color: lightblue;padding: 20px;border: 1px solid black;background-clip: content-bo…

06C内存分配

C零碎语法 目录 文章目录 C零碎语法1.内存布局2. 内存对齐2.1结构体内存对齐2.1应用 1.内存布局 2. 内存对齐 2.1结构体内存对齐 三条原则&#xff1a; &#xff08;1&#xff09;结构体变量的 起始地址能够被其最宽的成员大小整除。 &#xff08;2&#xff09;结构体每个…

前端Vue自定义滚动卡片组件设计与实现

摘要 随着技术的日新月异&#xff0c;前端开发的复杂度不断提升。传统的整块应用开发方式在面对小的改动或功能增加时&#xff0c;常常需要修改大量的整体逻辑&#xff0c;造成开发效率低下和维护成本高昂。为了应对这一挑战&#xff0c;组件化开发应运而生。本文将以Vue框架下…

Vue3项目练习详细步骤(第二部分:主页面搭建)

主页面搭建 页面主体结构 路由 子路由 主页面搭建 页面主体结构 在vuews目录下新建Layout.vue文件 主页面内容主体代码 <script setup> import {Management,Promotion,UserFilled,User,Crop,EditPen,SwitchButton,CaretBottom } from element-plus/icons-vue imp…

YOLOv5改进(六)--引入YOLOv8中C2F模块

文章目录 1、前言2、C3模块和C2F模块2.1、C3模块2.2、BottleNeck模块2.3、C2F模块 3、C2F代码实现3.1、common.py3.2、yolo.py3.3、yolov5s_C2F.yaml 4、目标检测系列文章 1、前言 本文主要使用YOLOv8的C2F模块替换YOLOv5中的C3模块&#xff0c;经过实验测试&#xff0c;发现Y…

C++之类的三种继承修饰符(public、private、protected)总结

1、前言 前文博客介绍了修饰符public、private、protected在类中成员变量和函数访问权限限制的总结&#xff0c;主要如下&#xff1a; public&#xff08;公有&#xff09;: 公有成员在类的内部和外部都可以被访问。 private&#xff08;私有&#xff09;: 私有成员只能在类的内…

Qt xml学习之calculator-qml

1.功能说明&#xff1a;制作简易计算器 2.使用技术&#xff1a;qml,scxml 3.项目效果&#xff1a; 4.qml部分&#xff1a; import Calculator 1.0 //需要引用对应类的队友版本 import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 1.4 import QtScxml…