mysql的各类索引

news2024/12/29 17:43:57

MySQL的索引分三类:单列索引(普通索引、唯一索引、主键索引)、多列索引(联合主键,组合索引)、全文索引

一、单列索引:一个索引只包含单个列,但一个表中可以有多个单列索引。

(1)普通索引(二级索引,非聚簇索引):MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值,纯粹是为了查询数据更快一点。

(2)唯一索引(二级索引,非聚簇索引):索引列中的值必须是唯一的,但是允许为空值。

(3)主键索引(聚簇索引):是一种特殊的唯一索引,非空且唯一。(主键约束,就是一个主键索引)。

主键索引与唯一索引的区别:

(1)主键是一种约束,唯一索引是一种索引,两者在本质上是不同的。

(2)主键创建后一定包含一个唯一性索引,唯一性索引并不一定是主键。

(3)唯一性索引列允许空值,而主键列不允许为空值。

(4)主键索引在创建时,已经默认为非空值+唯一索引了。

(5)一个表最多只能创建一个主键索引,但可以创建多个唯一索引。

(6)主键更适合那些不容易更改的唯一标识,如自动递增列、身份证号等。

(7)主键可以被其他表引用为外键,而唯一索引不能。

二、多列索引:一个多列索引包含多个列

1.联合主键

1)什么是联合主键

(也叫复合主键、组合主键),一个表中有多个主键列组合在一起,叫联合主键,一个表中只能有一个联合主键.

create table test
(
   name varchar(19),
   id number,
   value varchar(10),
   primary key (name,id)
)

2)为什么要使用联合主键

比如一个部门人员表,你不想单独建一个id列作为主键的话,就可以用 部门列 和 员工name 列都设为主键,作为表的联合主键,这样也可以保证表中每行数据都不重复.

2.组合索引

1)什么是组合索引

(也叫复合索引、联合索引),组合索引是不含主键索引的,是多个普通索引组合在一起的.一个表中可以有多个组合索引.

ALTER TABLE mytable ADD INDEX name_city_age (name,age,city);

把一个表的name,age,city三个非主键列设为一个组合索引,数据库实际上自动为我们设立了3个索引,分别是(name)        (name,age)       (name,age,city)

2)为什么要使用组合索引

  • 减少开销。
    建一个联合索引(col1,col2,col3),实际相当于建了(col1),(col1,col2),(col1,col2,col3)三个索引。比分别建立索引(col1),(col2),(col3)少了两个索引.        每多一个索引,都会增加写操作的开销和磁盘空间的开销。对于大量数据的表,使用联合索引会大大的减少开销!
  • 覆盖索引。
    对联合索引(col1,col2,col3),如果有如下的sql: select col1,col2,col3 from test where col1=1 and col2=2。那么MySQL可以直接通过遍历索引取得数据,而无需回表,这减少了很多的随机io操作。减少io操作,特别的随机io其实是dba主要的优化策略。所以,在真正的实际应用中,覆盖索引是主要的提升性能的优化手段之一。

3.最左原则

联合主键和组合索引都要遵守最左原则.

怎么查询才能保证全部走索引呢,那么就是要保证最左原则.

1.where条件后面必须含有第一个列name, 

2.顺序不能跳,就是不能是name和city,而没有age.

3.where条件后面的name和age在写在前后都无所谓.

走全部索引的例子:

SELECT * FROM mytable WHREE name="admin"


SELECT * FROM mytable WHREE name="admin" AND age= 20

SELECT * FROM mytable WHREE age= 20 AND  name="admin" 

SELECT * FROM mytable WHREE name="admin" AND age= 20  AND city ="北京"

SELECT * FROM mytable WHREE city ="北京" AND name="admin" AND age= 20  

走部分索引的例子:

SELECT * FROM mytable WHREE name="admin" AND city ="北京"

完全没走索引的例子:

SELECT * FROM mytable WHREE age= 20
SELECT * FROM mytable WHREE age= 20 AND   city ="北京"

三、全文索引:

在大量数据中,通过其中的某个关键字,就能找到该字段所属的记录行。全文索引在开发中很少用,因为其占用很大的物理空间和降低了记录修改性。


 

四. 索引在B+树的工作原理

1.我先建了一个表

CREATE TABLE `user_innodb` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `gender` tinyint(1) DEFAULT NULL,
  `phone` varchar(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

我创建了一个存储引擎为InnoDB的表user_innodb,其中包含主键id、姓名字段(name)、性别字段(gender,用0,1表示不同性别)、手机号字段(phone),并批量初始化了500W+条数据。

2.主键索引(聚簇索引)

上图就是mysql的innodb引擎根据我们设的id自动为我们生成的一个主键B+树索引结构,我们给它取了个名字,叫主键索引.又叫做聚簇索引.

主键索引有两个特点:

  1. 按照主键的大小对用户记录和数据页进行排序,记录用单向链表连接,叶子节点使用双向链表连接;
  2. B+树的叶子节点保存了用户的完整记录。

3.普通索引(二级索引,非聚簇索引) 

主键索引是在搜索条件为主键的时候才会发挥作用,但是我要以name='蝉沐风'为搜索条件怎么办?

innodb的解决办法就是再创建一个B+树(我们称为name索引),这就是普通索引.

这棵普通索引的B+树和聚簇索引的B+树有点区别:

  1. 叶子节点存放的不再是完整的用户记录,而是只记录name列和主键值;
  2. 数据页中存放的用户记录和目录项记录由原本的按照主键排序变为按照name列排序;
  3. 目录项记录除了存储索引列(name)和页号之外,同时还存储了主键值;(大家可以想一想,为什么要存储主键值,因为name列可能不是唯一的,如果两个name相同,那么谁排前面谁排后面呢,这时候就要按主键值来排序了.)

有了这棵B+树,你就可以通过name列快速找到主键值了,查找的方式和根据主键值查找用户记录的方式完全一样,只不过前者查到的是主键值,后者查找到的是一条完整的用户记录罢了。

你可能对字符串进行二分法感到有点奇怪,甚至没有接触过的相关知识的读者连对字符串进行排序都会觉得很诧异。其实在创建表的时候我们可以对字符串字段指定字符集和比较规则,如果你不指定,MySQL会默认给你设置,总之,MySQL总会找到一个方式对字符串进行排序。

现在得到主键的id了,然后根据主键id到主键索引中查找到完整的用户记录,这个过程叫做回表。如果没有为name列设置唯一性约束,那就可能找到多个符合条件的主键id,多回几次表就可以了。

name这种单个列添加的索引叫做普通索引,也叫二级索引

4.组合索引

(也叫复合索引、联合索引)

假设我们为name列和phone列建立联合索引(注意我描述的顺序,name列在前,phone列在后,后面的图的顺序也就是按这个顺序排的),自然也是创建一棵B+树,这棵B+树和之前又稍微有点不同:

  1. 叶子节点存放的是name列、phone列和主键值;
  2. 目录项记录除了存储索引列(namephone)和页号之外,同时还存储了主键值;(大家可以想一想,为什么要存储主键值)
  3. 数据页中存放的用户记录和目录项记录由原本的按照主键排序变为按照name列排序,如果name列相同,那就按照phone列排序;(如果phone列再一样呢?你现在明白为什么要存储主键值了吗?)

 再画个图吧(有点偷懒了哈,数据页号没换):

还是和二级索引一样,利用B+树快速定位到数据页,然后页内快速定位到记录,找到记录中的主键id,再回表,如果找到多条符合条件的记录,就多回几次表。

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

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

相关文章

阿里巴巴最受欢迎的10本书,希望能帮助你开阔眼界

读书是一件充实生活、丰富精神的事情,世界是复杂的,我们可以从书中获得包罗万象的知识,精神体验从未有过的人生。 书荒?不存在的,好书互相分享才能发挥其最大的价值。我们在内部发起了一个“晒一本你在读的书”的活动…

MyBatis 中如何使用结果映射

MyBatis 中如何使用结果映射 MyBatis 是一个开源的 Java 持久化框架,它可以将数据库中的数据映射到 Java 对象中,并且使得 Java 对象可以非常方便地存储到数据库中。在 MyBatis 中,结果映射是一个非常重要的概念,它可以将 SQL 查…

List类详解【c++】

🐔博主码云 🐔博主主页 目录 🐓list简介🐓list使用🐤list构造函数🐤list迭代器🐤list capacity🐤list element access🐤list modifiers🐤list的迭代器失效 &a…

ETH-S7200-JM01以太网模块在纺机设备网络中应用成功案例分析

内容摘要 大家好,今天我们要为大家介绍一款神奇的设备——捷米特ETH-S7200-JM01以太网模块!它可以让西门子PLC200 CPU226拥有以太网通讯接口,实现数据采集和生产管理系统构建。你以为这就是它的全部功能?那你就大错特错了&#x…

【STM32MP135】修改10.1寸屏1280x800分辨率配置,解决fb_size过小导致运行崩溃

文件路径:u-boot-stm32mp-v2021.10-stm32mp1-r1/configs/stm32mp13_defconfig

官网下载idea历史版本

1.进入官网 官网下载地址:https://www.jetbrains.com.cn/idea/ 进入后是这样的,如下图: 2.点击【下载】按钮,进入下载页面 (上图中的两个地方的【下载】按钮是一样的)。 3.选择右下角的【其他版本】就可…

LayUI入门,以及介绍

一.LayUI基本情况 1.LayUI介绍 Layui(流行于 layui.com)是一款轻量级的前端UI框架,专注于提供简洁、易用、灵活的界面组件和交互体验。它基于HTML5和CSS3技术,采用模块化开发的思想,提供了丰富的UI组件、常用的工具函数…

FTP服务器使用及配置

vsftp安装配置 环境配置 服务端:CentOS 7.6 vsftpd 客户端:Windows 10 xftp 服务端 yum -y install epel-release.noarchyum -y install vsftpd* pam* db4*systemctl restart vsftpd#修改配置前备份文件 [rootnode1 ~]# cd /etc/vsftpd/ [rootnode1 vsftpd]# ls ftpusers …

Eclipse调整系统字体(亲测)

1. 打开eclipse的菜单栏windows->preferences 2. 选择General->Appearance->colors and fonts 3. 选择字号,Apply,ok 建议选择常规18号,这样对眼睛友好一些,不易太大太小 为了大家更好的学习交流,博主新建了v…

算法训练营第三十五天||860.柠檬水找零 ● 406.根据身高重建队列 ● 452. 用最少数量的箭引爆气球

860.柠檬水找零 这道题自己不看答案能自己做出来 class Solution { public:bool lemonadeChange(vector<int>& bills) {if(bills[0]10 || bills[0]20) return false;int fivenum 0;int tennum 0;int tewentynum 0;for(int i 0;i<bills.size();i){if(bills[…

Hyper-V 虚拟机安装Ubuntu

Hyper-V 是win自带的虚拟机软件&#xff0c; 免费 进入控制面板&#xff0c;启用功能 勾选Hyper-V 然后重启电脑 打开 Hyper-v快速创建 此处可能需要 science surf network&#xff0c;否则创建虚拟机按钮为灰色 选择合适的版本&#xff0c;点击右下角的创建虚拟机进行安装&a…

【云时代数据利器】奥威BI SaaS版:一键链接云星空,套用百张报表

SaaS模式可以有效加快部署、提高效率、降低成本、提高灵活性&#xff0c;因此广受欢迎。随着市场的需求以及SaaS模式的广为人知&#xff0c;SaaS BI正逐渐成为BI的未来趋势之一&#xff0c;正逐渐成为云时代数据分析利器。奥威BI SaaS版和金蝶云星空标准方案强强联合&#xff0…

C++学习 结构体

目录 结构体 结构体定义和使用 结构体数组 结构体指针 结构体嵌套结构体 结构体做函数的参数 结构体中const使用场景 结构体 结构体定义和使用 定义&#xff1a; 结构体属于用户自定义的数据类型&#xff0c;允许用户存储不同的数据类型。 语法&#xff1a; struct 结构体…

day4 qtqtqtc++

cppcpp ui代码 <?xml version"1.0" encoding"UTF-8"?> <ui version"4.0"><class>Widget</class><widget class"QWidget" name"Widget"><property name"geometry"><rec…

Linux--获取与杀死当前进程PID

获取当前进程的代码&#xff1a; #include <sys/types.h>pid_t idgetpid();//获取的是自己的进程PID 杀死当前进程的指令&#xff1a; kill -9 进程的PID 我要是kill -9 16865(-bash进程)&#xff0c;你会发现无论你输入clear、ls、还是vim...指令&#xff0c;都无…

云深处绝影四足机器人协议学习解析

绝影四足机器人通信协议学习解析 本学习文档介绍了云深处 绝影X20 四足机器人的通信协议&#xff0c;并对相关的通信机制和命令格式进行了简单的解析。该协议在机器人系统和上位机&#xff08;例如外部板卡或系统&#xff09;之间进行TCP通信时使用。 1. 协议端口号 在此协议…

定义一个派生自D1的D2类,并且在D2中覆盖pvf();建立一个D2类的对象并且调用f()、vf()、pvf()

运行代码&#xff1a; //定义一个派生自D1的D2类&#xff0c;并且在D2中覆盖pvf() //建立一个D2类的对象并且调用f()、vf()、pvf() #include"std_lib_facilities.h" //---------------------------------------------------------------------- //定义B1类。 class …

配置通过域名访问网站(NETBASE第七课)

1 DNS服务器 域名系统_百度百科 域名和与之相对应的IP地址转换的服务器 DNS&#xff08;Domain Name Server&#xff0c;域名服务器&#xff09;是进行域名(domain name)和与之相对应的IP地址 (IP address)转换的服务器。DNS中保存了一张域名(domain name)和与之相对应的IP地…

通过GitHub Desktop,将本地项目上传到gitee上

介绍 这里主要介绍&#xff0c;通过 gitHub Desktop 软件&#xff0c;将本地的项目&#xff0c;上传到 gitee的仓库里&#xff08;这里仓库为新建的仓库&#xff0c;什么东西都没有&#xff09;。 这里主要介绍&#xff0c;仓库的新建方式&#xff0c;及本地代码上传到远端的操…

Unity 实现一个揭面膜效果

源码 using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI;