Mysql数据库(性能)索引学习
目录
1. 什么是索引?索引的优缺点?
1.2 索引的优点
1.3 索引的缺点
1.4 如何正确地使用索引?
2. Mysql慢查询该如何优化?
3. 索引覆盖是什么
4.最左前缀原则是什么
5. B树和B+树的区别,为什么Mysql使⽤B+
6. Mysql锁有哪些,如何理解
7.数据库三大范式是什么(经典核心)
8.MySQL存储引擎MyISAM与InnoDB区别
9. MyISAM索引与InnoDB索引的区别?
9.1 非聚簇索引一定会回表查询吗?
前言
mysql的性能优化几乎都是和索引打交道,当然也有批处理、表结构设计了等,主要是还是搞索引。
1. 什么是索引?索引的优缺点?
1.1 索引的定义:
是帮助Mysql高效获取数据的排好序的数据结构。
1.2 索引的优点
-
极大提高查询速度
这是索引最主要、最核心的优点。通过索引,数据库可以直接定位到所需数据的位置,避免了全表扫描,尤其对于大型表,性能提升是数量级的。这是以空间换时间的经典策略。 -
确保数据的唯一性
唯一索引(UNIQUE INDEX
)可以保证表中每一行数据的唯一性,防止重复数据的插入。例如,为用户的身份证号字段创建唯一索引,可以确保不会录入两个身份证号相同的用户。 -
加速表之间的连接
在进行多表连接(JOIN
)查询时,如果连接条件上的字段建立了索引,会大幅提高连接查询的性能。 -
减少分组和排序的时间
使用ORDER BY
和GROUP BY
子句进行排序和分组时,如果排序或分组的字段上有索引,数据库可以直接利用索引的有序性来完成操作,避免了昂贵的临时表排序和文件排序。
1.3 索引的缺点
-
占用额外的磁盘空间
索引需要创建并存储额外的数据结构(如B+Tree)。一张表的索引大小甚至可能超过数据本身的大小。这意味着你需要更多的存储空间。 -
降低数据写入(增、删、改)的速度
这是一个非常重要的缺点。当对表中的数据进行INSERT
、UPDATE
、DELETE
操作时,数据库不仅需要操作数据本身,还需要更新与之相关的所有索引来保持数据一致性。这意味着每次写入操作都伴随着额外的磁盘I/O和计算开销。索引越多,写入性能受到的负面影响就越大。 -
需要维护成本
索引不是一劳永逸的。随着数据的不断增删,索引结构中会产生碎片,导致性能下降。因此,数据库管理员(DBA)需要定期对索引进行优化或重建(如OPTIMIZE TABLE
)来维护其性能。
总结与使用建议
方面 | 优点 | 缺点 |
---|---|---|
查询性能 | 极大提升 SELECT 查询速度 | - |
写入性能 | - | 降低 INSERT, UPDATE, DELETE 速度 |
空间占用 | - | 占用额外磁盘空间 |
数据完整性 | 保证唯一性(唯一索引) | - |
维护 | - | 需要定期维护以避免性能下降 |
1.4 如何正确地使用索引?
-
在需要的地方创建:只为经常出现在
WHERE
、ORDER BY
、GROUP BY
、JOIN ON
子句中的字段创建索引。 -
考虑列的区分度:选择区分度高(即重复值少)的列建索引。例如,“性别”列只有‘男’,‘女’等几个值,建索引效果几乎为零;而“身份证号”列区分度极高,建索引效果非常好。
-
避免过度索引:不要为每列都创建索引。索引是“好东西,但不是越多越好”。每个额外的索引都会增加存储开销并拖慢写入速度。
-
使用复合索引:如果一个查询经常同时用到多个字段,考虑创建复合索引(多列索引)。复合索引的字段顺序很重要,应遵循最左前缀原则。
2. Mysql慢查询该如何优化?
-
检查是否⾛了索引,如果没有则优化SQL利⽤索引
-
检查所利⽤的索引,是否是最优索引
-
检查所查字段是否都是必须的,是否查询了过多字段,查出了多余数据
-
检查表中数据是否过多,是否应该进⾏分库分表了
-
检查数据库实例所在机器的性能配置,是否太低,是否可以适当增加资源
3. 索引覆盖是什么
索引覆盖就是⼀个SQL在执⾏时,可以利⽤索引来快速查找,并且此SQL所要查询的字段在当前索引对 应的字段中都包含了,那么就表示此SQL⾛完索引后不⽤回表了,所需要的字段都在当前索引的叶⼦节 点上存在,可以直接作为结果返回了
4.最左前缀原则是什么
当⼀个SQL想要利⽤索引是,就⼀定要提供该索引所对应的字段中最左边的字段,也就是排在最前⾯的 字段,⽐如针对a,b,c三个字段建⽴了⼀个联合索引,那么在写⼀个sql时就⼀定要提供a字段的条件,这 样才能⽤到联合索引,这是由于在建⽴a,b,c三个字段的联合索引时,底层的B+树是按照a,b,c三个字段 从左往右去⽐较⼤⼩进⾏排序的,所以如果想要利⽤B+树进⾏快速查找也得符合这个规则
5. B树和B+树的区别,为什么Mysql使⽤B+
-
B树:每个节点都存储键(Key)和对应的数据(Data)。查询可能在非叶子节点就结束。
-
B+树:只有叶子节点(Leaf Node)存储数据,非叶子节点(Non-Leaf Node)只存储键和指向子节点的指针(导航作用)。所有查询都必须走到叶子节点才能拿到数据,且叶子节点之间通过指针相连,形成一个有序链表。
对比表格如下:
特性 | B树 | B+树 (MySQL InnoDB使用) |
---|---|---|
数据存储位置 | 所有节点(包括非叶子节点)都存储数据。 | 仅在叶子节点存储数据。非叶子节点只作为索引。 |
查询性能 | 最好情况(命中非叶子节点)很快,不稳定。 | 非常稳定。任何查询都必须走一条从根到叶子的路径,耗时均衡。 |
叶子节点链接 | 叶子节点之间没有指针相互链接。 | 所有叶子节点通过双向指针串联成一个有序链表。 |
范围查询 | 效率低。需要进行复杂的中序遍历。 | 效率极高。找到范围下界后,只需沿链表顺序扫描即可。 |
空间利用率 | 相对较低,因为每个节点都存储数据,导致一页(Page)中能存放的键更少,树更高。 | 更高。非叶子节点不存数据,一页能存放更多键,树更矮胖,减少了磁盘I/O次数。 |
扫描全表 | 需要对整棵树进行中序遍历。 | 只需遍历叶子节点链表即可,非常高效。 |
Mysql索引使⽤的是B+树,因为索引是⽤来加快查询的,⽽B+树通过对数据进⾏排序所以是可以提⾼查 询速度的,然后通过⼀个节点中可以存储多个元素,从⽽可以使得B+树的⾼度不会太⾼,在Mysql中⼀ 个Innodb⻚就是⼀个B+树节点,⼀个Innodb⻚默认16kb,所以⼀般情况下⼀颗两层的B+树可以存2000 万⾏左右的数据,然后通过利⽤B+树叶⼦节点存储了所有数据并且进⾏了排序,并且叶⼦节点之间有指 针,可以很好的⽀持全表扫描,范围查找等SQL语句。
6. Mysql锁有哪些,如何理解
按锁粒度分类:
1. ⾏锁:锁某⾏数据,锁粒度最⼩,并发度⾼
2. 表锁:锁整张表,锁粒度最⼤,并发度低
3. 间隙锁:锁的是⼀个区间
还可以分为:
1. 共享锁:也就是读锁,⼀个事务给某⾏数据加了读锁,其他事务也可以读,但是不能写
2. 排它锁:也就是写锁,⼀个事务给某⾏数据加了写锁,其他事务不能读,也不能写
还可以分为:
1. 乐观锁:并不会真正的去锁某⾏记录,⽽是通过⼀个版本号来实现的
2. 悲观锁:上⾯所的⾏锁、表锁等都是悲观锁
7.数据库三大范式是什么(经典核心)
-
第一范式:每个列都不可以再拆分。
-
第二范式:在第一范式的基础上,非主键列完全依赖于主键,而不能是依赖于主键的一部分。
-
第三范式:在第二范式的基础上,非主键列只依赖于主键,不依赖于其他非主键。
8.MySQL存储引擎MyISAM与InnoDB区别
-
事务与外键 (Transaction & Foreign Key)
-
InnoDB: 这是两者最核心的区别。InnoDB 提供了完整的 ACID(原子性、一致性、隔离性、持久性)事务支持,并支持外键约束。这使得它非常适合需要保证数据一致性和完整性的应用,如金融、订单管理等系统。
-
MyISAM: 完全不支持事务和外键。如果执行过程中发生错误,无法回滚,可能导致数据处于不一致的状态。
-
-
锁机制 (Locking Mechanism)
-
InnoDB: 支持行级锁。当只修改某一行数据时,只需要锁定这一行,其他行仍然可以被并发读写。这极大地提高了高并发写操作下的性能和吞吐量。
-
MyISAM: 只支持表级锁。任何写操作(INSERT, UPDATE, DELETE)都会锁住整个表,在此期间其他所有读写操作都必须等待。在读多写少的场景下可能问题不大,但在写并发高的场景下会成为严重的性能瓶颈。
-
-
索引结构 (Index Structure)
-
InnoDB: 使用聚集索引。表数据文件本身就是按主键索引组织的一个 B+Tree 结构,叶子节点直接存储了完整的行数据。因此,基于主键的查询速度极快。
-
MyISAM: 使用非聚集索引。索引文件(.MYI)和数据文件(.MYD)是分离的。索引的叶子节点存储的是指向数据文件所在位置的指针。这意味着主键查询需要多一次寻址。
-
-
崩溃恢复 (Crash Recovery)
-
InnoDB: 通过 Write-Ahead Logging 技术,所有事务在提交前都会先写入 redo log。即使在写入数据时系统崩溃,重启后也能根据 redo log 自动恢复已提交的事务,保证数据不丢失。
-
MyISAM: 没有这种机制。发生意外断电或崩溃后,表很容易损坏,需要执行检查甚至修复操作(
CHECK TABLE
/REPAIR TABLE
),可靠性较差。
-
引擎 | 优点 | 缺点 | 现状 |
---|---|---|---|
InnoDB | 事务、行级锁、崩溃恢复好、外键、缓存效率高 | COUNT(*) 慢、相对占用更多磁盘空间 | 绝对主流,默认选择 |
MyISAM | COUNT(*) 快、全文索引(旧版)、结构简单 | 表锁、无事务、崩溃后易损坏 | 已被淘汰,仅用于遗留系统或特殊场景 |
9. MyISAM索引与InnoDB索引的区别?
聚簇索引和非聚簇索引定义如下:
- 聚簇索引:将数据存储与索引放到了一块,找到索引也就找到了数据
- 非聚簇索引:将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行,myisam通过key_buffer把索引先缓存到内存中,当需要访问数据时(通过索引访问数据),在内存中直接搜索索引,然后通过索引找到磁盘相应数据,这也就是为什么索引不在key buffer命中时,速度慢的原因
- InnoDB索引是聚簇索引,MyISAM索引是非聚簇索引。
- InnoDB的主键索引的叶子节点存储着行数据,因此主键索引非常高效。
- MyISAM索引的叶子节点存储的是行数据地址,需要再寻址一次才能得到数据。
- InnoDB非主键索引的叶子节点存储的是主键和其他带索引的列数据,因此查询时做到覆盖索引会非常高效。
9.1 非聚簇索引一定会回表查询吗?
-
不一定,这涉及到查询语句所要求的字段是否全部命中了索引,如果全部命中了索引,那么就不必再进行回表查询。
-
举个简单的例子,假设我们在员工表的年龄上建立了索引,那么当进行
select age from employee where age < 20
的查询时,在索引的叶子节点上,已经包含了age信息,不会再次进行回表查询。