【MySQL】索引

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 哈喽,大家好~我是保护小周ღ,本期为大家带来的是 MySQL 数据库中表的索引,详细得讲解了索引得基本概念,使用场景,如何添加索引,删除索引,展示索引,以及索引背后的数据结构,确定不来看看~更多相关知识敬请期待:保护小周ღ *★,°*:.☆( ̄▽ ̄)/$:*.°★*

一、索引

1.1 索引的概念

当我们是使用查询语句对表中的数据进行条件查询的时候,MySql 服务器会对该表中的数据进行条件遍历,即每一条记录都会判断,时间复杂度是 O(N)。

当我们涉及到多表联合查询时,多表数据就会形成一个笛卡尔积——数据库中的数据都是以二维表的形式存放的,记录就是表格的行,字段就是其中的每个列, 笛卡尔积就是把多个表中的所有数据进行(全部预设的组合),举个例子:

学生表 stu:

成绩表:grade

我们对这两张表进行联合查询。

这里博主展示了全部字段,所以两个表中的数据有所重复,这里使用 Right Join 进行右连接,on 后面是连接匹配的条件,right join 以左表(学生表)为主,在右表(成绩表)中根据匹配条件查找,例如:成绩表中的 id 字段需要和学生表中的 id 字段有所匹配,左表中有符合条件的数据就返回数据与右表进行组合。

这是建立在我们设置了连接条件的基础上,如果我们没有设置条件,两张表就会生成笛卡尔积。

由上图可见,笛卡尔积就是将两张表的数据进行无规则的排列组合,即使数据是错误的,也会排列出来,当我们设置了条件进行条件查询,就会在笛卡尔积中遍历寻找符合条件的数据,形成一张新的数据集合返回客户端,展示给用户,笛卡尔积有多少行记录,取决于,多表中有多少条记录,即: stud 表中记录数 和 grade 表中记录数的乘积,这两张表才只插入了3行记录,笛卡尔积就有9 行, 如果两表中各有 100条记录, 笛卡尔积就有 100 * 100 (10000)行记录,在这种情况下,遍历查询的效率就非常低了。


创建索引的目的就是为了能够快速的定位、检索数据,索引我们可以先理解为是根据字段创建的指向对应记录的指针。

如果搜索条件的列上已经创建了索引,MySQL服务器无需扫描任何记录即可迅速得到目标记录所在的位置。


1.2  索引的运用

索引的创建使用需要考虑一些情况:

索引一般创建于数据量特别大的情况下 索引可以针对一列或者是多列创建,创建于需要经常对这些列进行条件查询的字段,例如 :学号 id 创建索引会占用额外的存储空间,服务器需要组织管理索引 创建索引的列必须能够进行比较,幸运的是 Mysql 提供的数据结构都能够比较。

1.2.1 索引的创建

当我们对数据表的字段创建主键约束 (PRIMARY KEY),唯一约束 (UNIQUE), 外键约束(FOREIGN)的时候,会自动的为这些字段创建索引, 这些字段也是常常被我们用来作为查询条件。

以下是在创建 (create)数据表时建立约束,当数据表创建完毕后,可以使用 ALTER 语句修改(不建议使用 ALTER 语句)。

对字段建立主键约束:

【字段名】 数据类型 primary key

对字段建立外键约束:

foreign key 【字段名】references 【主表】(主键字段或者唯一字段)

对字段建立唯一约束:

【字段名】 数据类型 unique

1.2.2 查看表的索引

show index from 【表名】

1.2.3 创建索引

针对并非 主键、外键、唯一约束的字段,创建索引

create index 索引名 on 【表名】(字段名)

举个例子: 为学生表的 sex 字段设置 引索

mysql>select*from stud;+--------+--------+------+| stu_id | name   | sex  |+--------+--------+------+|1| 张三   |||2| 李四   |||3| 王六   ||+--------+--------+------+3 rows inset(0.00 sec)mysql>create index gender on stud(sex);Query OK,0 rows affected (0.02 sec)Records:0  Duplicates:0  Warnings:0mysql> show index from stud;+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+|Table| Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed |Null| Index_type | Comment | Index_comment |+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+| stud  |0| PRIMARY  |1| stu_id      | A         |3|NULL|NULL|| BTREE      |||| stud  |1| gender   |1| sex         | A         |2|NULL|NULL| YES  | BTREE      |||+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+2 rows inset(0.00 sec)

以上是建立在数据表已经创建好的情况下,在创建数据表的时候可以直接为字段创建约束。

创建一个学生表 stu2 ,有 id ,name, sex 字段,并为 id 字段创建 索引。

mysql>createtable if not exists ()->;ERROR 1064(42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '()' at line 1mysql>createtable if not exists stud2 (-> id int,-> name varchar(20),-> sex varchar(3),-> index(id));Query OK,0 rows affected (0.02 sec)mysql> show index from stud2;+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+|Table| Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed |Null| Index_type | Comment | Index_comment |+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+| stud2 |1| id       |1| id          | A         |0|NULL|NULL| YES  | BTREE      |||+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+1 row inset(0.00 sec)

1.2.4 删除索引

drop index 【索引名】 on 【表名】

删除刚刚 为 stud 学生表 sex 字段创建的名为 gender 的索引

mysql>drop index gender on stud;Query OK,0 rows affected (0.01 sec)Records:0  Duplicates:0  Warnings:0mysql> show index from stud;+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+|Table| Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed |Null| Index_type | Comment | Index_comment |+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+| stud  |0| PRIMARY  |1| stu_id      | A         |3|NULL|NULL|| BTREE      |||+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+1 row inset(0.00 sec)

1.2.5 总结

我们创建索引有4种方式:

  1. 为表中的某些字段设置 主键,外键,唯一约束
  2. 使用 create index 索引名 on 【表名】(字段名) 语句
  3. 可以在创建数据表的时候 使用index(字段)创建索引
  4. 可以使用 ALTER 语句创建索引,也可以给字段添加主键,外键等,只不过是其他的语法,感兴趣的朋友可以观看博主的另一篇博客,表的基本数据类型及表的处理
ALTER TABLE table_name ADD INDEX index_name (column_list);

注意:我们创建索引的时候,或者是主键,尽量提前设计好表的结构,在创建表的时候就把这些约束啥的弄好,或者是在表刚刚创建完毕,还没有插入数据的时候 使用 ALTER 语句对表的结构进行修改,不建议在有很多数据的时候给字段添加索引,因为当数据量过多的时候创建索引对空间和时间开销很大,比如说几百万数据建立索引,系统需要分配大量的资源来存储和管理索引,就会引起数据库的卡顿或者是崩溃。

创建索引的目的就是为了加快MySql 服务端对数据检索的效率,当然这是建立在条件查询的基础之上,主要就是对我们经常作为查询条件的字段创建索引是比较好的选择,索引虽好,需要我们能够把握好他的使用场景,从某种意义上来说创建索引的开销也是很大的。


二、索引底层的数据结构

管理索引底层的数据结构是 B+ 树,说起 B+树,不知道有没有朋友了解过 二叉搜索树呢, B + 树是 B树的基础上做的优化改进, 可以理解为他们是 N 叉搜索树,

B+ 树的特点

key 值——创建索引得字段值

  1. 一个节点可以存储 N个 key值, N 个key 值划分出 N 个区间 (一个key 值划分一个区间)
  2. 每个节点中key 的值(父),会作为子节点的最大值出现在子节点中
  3. B + 树的叶子节点依次链接,类似于一个链表的结构
  4. 因为每个key 值都会划分出 N 个区间,每个key 值都会以最大值的形式在子节点中出现,所以

B+ 树的叶子节点就包含了所有的 key 值,我们也只需要在叶子节点中存储数据表中每一行的数据。


为什么会使用B+ 树作为索引的底层结构呢

B+ 树的实质是 N叉搜索树,相对于二叉搜索树来说,一个节点可以保存更多的 Key ,树的高度会相对来说低,所以查询的效率更高,这就意味着降低了对硬盘的访问次数,MySql 本身就是依托于硬盘存储,数据总归是会被读取到内存中处理的。

B+ 树的叶子节点相互构成链表,适合进行范围查询,找到了指定的 Key 值,Key 值得前后就是范围,顺着指针遍历。

B+ 树叶子节点存储了每一条记录,非叶子节点只需要存储 key 值(创建索引得字段值),所以非叶子节点所占得存储空间比较少,也可以降低硬盘访问数据量。


到这里,Mysql 系列索引相关的知识博主已经分享完了,希望对大家有所帮助,如有不妥之处欢迎批评指正。


下一期:MySQL  数据库事务

感谢每一个观看本篇文章的朋友,更多精彩敬请期待:保护小周ღ *★,°*:.☆( ̄▽ ̄)/$:*.°★*

遇见你,所有的星星都落在我的头上……

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
14天前
|
存储 自然语言处理 关系型数据库
MySQL高级篇——索引的创建与设计原则
索引的分类与使用、MySQL8.0索引新特性、适合创建索引的情况、不适合创建索引的情况
MySQL高级篇——索引的创建与设计原则
|
14天前
|
存储 SQL 关系型数据库
MySQL高级篇——索引失效的11种情况
索引优化思路、要尽量满足全值匹配、最佳左前缀法则、主键插入顺序尽量自增、计算、函数导致索引失效、类型转换(手动或自动)导致索引失效、范围条件右边的列索引失效、不等于符号导致索引失效、is not null、not like无法使用索引、左模糊查询导致索引失效、“OR”前后存在非索引列,导致索引失效、不同字符集导致索引失败,建议utf8mb4
MySQL高级篇——索引失效的11种情况
|
23天前
|
存储 关系型数据库 MySQL
MySQL基础:索引
MySQL中的索引是一种数据结构,能大幅提升数据库查询效率和减少I/O成本,类似于书的目录帮助快速定位内容。其优势包括提高检索效率和降低排序成本,但会占用空间并影响更新表的效率。鉴于查询远多于更新,索引仍被推荐使用。索引分为多种类型,如B+树和哈希索引,其中B+树因其较低的高度和稳定的查询开销成为常用选择。创建和删除索引需谨慎,以免影响性能。
42 4
MySQL基础:索引
|
14天前
|
存储 SQL 关系型数据库
【MySQL调优】如何进行MySQL调优?从参数、数据建模、索引、SQL语句等方向,三万字详细解读MySQL的性能优化方案(2024版)
MySQL调优主要分为三个步骤:监控报警、排查慢SQL、MySQL调优。 排查慢SQL:开启慢查询日志 、找出最慢的几条SQL、分析查询计划 。 MySQL调优: 基础优化:缓存优化、硬件优化、参数优化、定期清理垃圾、使用合适的存储引擎、读写分离、分库分表; 表设计优化:数据类型优化、冷热数据分表等。 索引优化:考虑索引失效的11个场景、遵循索引设计原则、连接查询优化、排序优化、深分页查询优化、覆盖索引、索引下推、用普通索引等。 SQL优化。
154 15
【MySQL调优】如何进行MySQL调优?从参数、数据建模、索引、SQL语句等方向,三万字详细解读MySQL的性能优化方案(2024版)
|
14天前
|
存储 缓存 关系型数据库
MySQL高级篇——存储引擎和索引
MyISAM:不支持外键和事务,表锁不适合高并发,只缓存索引,内存要求低,查询快MyISAM提供了大量的特性,包括全文索引、压缩、空间函数(GIS)等,但MyISAM不支持事务、行级锁、外键,有一个毫无疑问的缺陷就是崩溃后无法安全恢复。5.5之前默认的存储引擎优势是访问的速度快,对事务完整性没有要求或者以SELECT、INSERT为主的应用针对数据统计有额外的常数存储。故而 count(*) 的查询效率很高表名.frm 存储表结构;表名.MYD 存储数据 (MYData);
MySQL高级篇——存储引擎和索引
|
14天前
|
存储 关系型数据库 MySQL
MySQL高级篇——覆盖索引、前缀索引、索引下推、SQL优化、主键设计
覆盖索引、前缀索引、索引下推、SQL优化、EXISTS 和 IN 的区分、建议COUNT(*)或COUNT(1)、建议SELECT(字段)而不是SELECT(*)、LIMIT 1 对优化的影响、多使用COMMIT、主键设计、自增主键的缺点、淘宝订单号的主键设计、MySQL 8.0改造UUID为有序
MySQL高级篇——覆盖索引、前缀索引、索引下推、SQL优化、主键设计
|
3天前
|
关系型数据库 MySQL 数据库
MySQL删除全局唯一索引unique
这篇文章介绍了如何在MySQL数据库中删除全局唯一的索引(unique index),包括查看索引、删除索引的方法和确认删除后的状态。
25 9
|
6天前
|
关系型数据库 MySQL 数据库
MYSQL索引的分类与创建语法详解
理解并合理应用这些索引类型,能够有效提高MySQL数据库的性能和查询效率。每种索引类型都有其特定的优势,适当地使用它们可以为数据库操作带来显著的性能提升。
22 3
|
1月前
|
缓存 关系型数据库 MySQL
在Linux中,如何优化MySQL性能,包括索引优化和查询分析?
在Linux中,如何优化MySQL性能,包括索引优化和查询分析?
|
1月前
|
SQL 关系型数据库 MySQL
MySQL索引你用对了吗?
本文从遇到的问题出发,分析了tddl优化器、MySQL索引、分表拆分键的选择相关知识。