MySQL索引【学习笔记】

一、索引的定义

MySQL索引是一种数据结构,它可以加速数据库中查找和检索数据的速度

【优点】

 1、提高数据检索的速度,降低数据库I/O成本,从而提高数据访问性能

 2、索引列默认对数据进行排序,降低数据排序的成本,从而降低了CPU的消耗

【缺点】

 1、建立索引,系统要占用大约为表的1.2倍的硬盘和内存空间来保存索引。

 2、更新数据时,系统必需要有额外的时间来同时对索引进行更新,以维持数据和索引的一致性。

二、Mysql索引底层数据结构

B+ 树【MySQL 索引使用的最常见的数据结构之一

既支持范围查询,也支持顺序遍历,也支持随机访问。

B+ 树是一颗多路平衡树,对于每个节点,它都有一个关键字和对应的指针。

B+ 树的内部节点存储的只是关键字和指针,数据存储在叶子节点,叶子节点间用单链表连接

扫描二维码关注公众号,回复: 16600974 查看本文章

与 B 树相比,B+ 树的叶子节点指针指向的是数据块,而非数据本身,降低了 I/O 操作成本

哈希表【在进行插入、删除、查找等操作时效率非常高的数据结构】

对于大量随机的访问,哈希表比 B+ 树等数据结构的效率更高。

在 MySQL 中,哈希表一般用于 Memory 存储引擎中,由于 Memory 存储引擎本身就是基于内存的,所以哈希表能够更好地利用内存资源,从而提高查询效率。

三、Mysql不同存储引擎的索引实现

MyISAM 存储引擎【基于B+ 树索引来实现,支持全文索引和空间索引,但不支持事务和行级锁】

InnoDB 存储引擎【对事务支持最好的存储引擎】【基于B+树索引实现,支持事务和行级锁】

在 InnoDB 存储引擎中,聚集索引的特殊之处在于其存储的数据和索引是放在同一颗B+ 树中的,也就是说索引和数据是共存储的。

Memory 存储引擎【基于哈希索引实现,支持高速读写,但不支持事务和持久化】

在 Memory 存储引擎中, 只有哈希索引,没有其他类型的索引,且哈希索引不支持排序,不支持范围查询,只支持等值查询。

CSV 存储引擎【本质:文本文件,不像其他引擎那么高效】

CSV 存储引擎提供的索引相当于是 MyISAM 存储引擎基于 B+ 树的索引实现(但 CSV 存储引擎并不支持 B+ 树),需要通过查询整个表来查找行数据。

四、索引的类型

  1. B-Tree索引:最常用的一种索引。通过将索引列的值按照一定的规则组织成树状结构,从而实现快速查找和检索。

  2. 哈希索引:这种索引是基于哈希值进行查找和检索的。它适用于在等值查询时进行高效的散列匹配,但在范围查询和模糊查询上效果不佳。

  3. 全文索引:这种索引适用于对文本内容进行搜索和检索。它可以对文本进行分词和建立倒排索引,从而实现高效的全文搜索。

  4. 空间索引:这种索引适用于对地理位置信息或其他空间数据进行搜索和检索。它可以对空间数据进行组织和索引,从而实现高效的空间查询和分析。

 【使用规则】

不同类型的索引适用于不同的场景和需求。在创建索引时需要根据具体情况进行选择。

同时,在设计数据表时也需要考虑到索引的创建和维护成本。 

  1. 索引的选择:在创建索引时需要选择合适的类型和列,不可盲目创建索引。一般来说,主键、外键、频繁被查询的列以及经常用来排序和分组的列适合创建索引

  2. 索引的数量:过多的索引会增加数据库的维护成本和查询时间,也会影响插入、更新和删除的性能,一般来说,每张表最好不要超过5个索引

  3. 索引的顺序:多列索引的顺序也会影响查询的效率。一般来说,将选择性较高的列放在索引前列更合适。

  4. 索引的更新:每次对被索引的列进行插入、更新和删除操作都需要更新索引,这会影响性能。因此,需要尽量减少对索引列的更新操作

  5. 索引的扫描:索引的扫描次数过多会增加查询的时间。因此,在查询时应尽量避免全表扫描,尽量使用覆盖索引、索引下推等优化方式

五、索引常见分类 

【单值索引】【复合索引】

单值索引是在单一列上创建的索引,而复合索引是在多个列上创建的组合索引。

复合索引会相对更加灵活,但也需注意优化查询顺序,保证查询能够最大限度地利用到索引


【聚簇索引】【非聚簇索引】

聚簇索引是表中主键列上的索引,会将数据按照主键值进行排序存储

非聚簇索引是针对非主键列上的索引


【唯一索引】【普通索引】

唯一索引的索引键值必须唯一,适用于需要保证数据完整性的场景。

普通索引没有唯一性限制,可重复。


【前缀索引】【全文索引】

前缀索引是只对索引的一部分字符进行索引,它可以节省索引空间,但会牺牲一定查询性能

全文索引可以在自然语言中进行模糊查询,需要MySQL的MyISAM存储引擎支持。

六、常见索引【建表时】

主键索引:用于保证表中每一行的唯一性,一般情况下都会创建。

外键索引:用于维护表与表之间的关系。当有关联关系的表格建立索引时,外键索引会自动创建。

唯一索引:用于保证某一列的唯一性,不允许重复。适用于需要保证数据完整性的场景。

非空索引:用于要求索引列中不允许存在空值(NULL)的索引。

自增索引:用于自动生成一个唯一的编号并作为索引的值,通常作为主键索引。

普通索引:用于提高查询效率,一般用于搜索、排序、分组等操作。

七、索引相关操作

1、【创建索引】【创建索引会消耗资源,并可能影响数据库的性能】

CREATE TABLE users (
  id INT PRIMARY KEY,
  name VARCHAR(255),
  age INT,
  INDEX idx_name_age (name, age)
);
CREATE [UNIQUE] INDEX index_name
ON table_name(column_name1 [ASC|DESC], column_name2 [ASC|DESC], ...)

 2、【删除索引】【如果删除了一个正在使用的索引,可能会导致查询变慢或出现其他问题】

ALTER TABLE table_name DROP INDEX index_name;
DROP INDEX index_name ON table_name;

  3、【修改索引】【如果删除了一个正在使用的索引,可能会影响表的原有业务和性能

先删除后创建
ALTER INDEX index_name ON table_name RENAME TO new_index_name;

   4、【查看索引】【建议使用 SHOW INDEX 命令,可以查看表的所有索引信息】

SHOW INDEX FROM table_name;
-- 索引名称、字段名称、索引类型、索引方法
DESCRIBE table_name;
-- 将显示指定表的所有字段信息,以及在每个字段上的索引信息(如果有的话)

八、索引失效常见情况

  1. 对索引列使用了函数操作,如使用了函数进行运算、转换或比较,这可能导致索引失效

  2. 对索引列进行了类型转换,例如将字符串类型的数据转换为数字类型进行比较,这可能也会导致索引失效。故在可能存在类型转换的情况下,最好将索引设定为相同的数据类型

  3. 对索引列使用了 OR 或 NOT 进行查询,这可能会导致索引失效。

  4. 在 SQL 语句中使用了 LIKE 来进行模糊查询,但是 LIKE 模式所匹配的字符串以通配符开头,这可能也会导致索引失效。

  5. 数据库表中数据的分布不均衡,例如某个值重复出现次数过多,这也可能会导致索引失效。

因此,在设计和使用索引时需要特别注意上述情况,并尽可能避免出现这些情况,以保证索引的有效性。 

九、【组合索引】

联合索引的创建原则:

1.考虑选择最常用于查询的列作为联合索引的前缀;

2.避免使用过多的列来创建联合索引,以免影响索引效率和占用存储空间;

3.对于高基数(唯一性较高)的列可以优先考虑加入联合索引;

4.尽量将区分度高的列放在联合索引前面,并且不同值的数量越大的列越适合作为前缀;

5.对于经常组合使用的列,可以考虑创建独立的索引;

联合索引的创建原则:

1、联合索引应该包含经常一起查询的列。

2、索引列的顺序应该优先考虑选择性高的列,即值的重复度低的列。

3、联合索引的列数不宜过多,否则会增加维护成本和索引存储空间。

4、联合索引只在需要查询第一个或前几个列的数据时才能发挥作用,如果查询中没有使用前面的列,则无法使用该索引。

5、当数据量很大时,使用联合索引可以显著提高查询效率,但对于小型数据集,可能会降低查询效率。

最左前缀匹配原则:

使用组合索引查询时,会一直向右匹配直至遇到范围查询(>、<、between、like)就停止匹配

十、覆盖索引【避免回表】

覆盖索引是一种优化技术,它允许查询只使用索引数据而不必回表查询实际数据

为实现覆盖索引,需要在索引中添加查询所需的所有列,使得查询可以完全由索引数据满足,而无需再到表中获取额外的数据。

回表【数据库查询优化中的一个概念

指的是当使用索引进行数据查询时,数据库需要在索引中找到对应的行记录后,再根据该行记录的主键值(或唯一索引值)去表中查找相应的完整数据记录。

【索引常见面试题】

请解释什么情况下应该使用复合索引?

复合索引适用于需要使用多个字段作为查询条件进行筛选的情况。

但是需要注意的是,复合索引有可能会让某些单一查询变得更加缓慢

什么是最左匹配原则?

最左匹配原则是指在使用复合索引进行查询时,最左前缀可以作为索引的查询条件,而不一定需要全部匹配。这个原则对于设计合适的索引非常重要。

MySQL 中如何判断一个查询是否会使用索引?

可以使用 EXPLAIN 关键字,在查询前加上 EXPLAIN 关键字,可以得到查询执行计划,其中会显示查询是否使用了索引。

删除表中的数据时,是否需要手动删除对应的索引?

不需要手动删除索引,当删除表中的行时,对应的索引会自动更新。

如果一个表中的记录数量非常少,是否需要创建索引?

不一定需要。若表中的记录数量非常少,索引的作用就不太明显了,反而会增加查询的负担而如果表中的记录数量增加到一定程度时,就有必要考虑是否需要创建索引。

请谈一下在项目中如何设计合适的索引?

在项目中设计索引时,需要根据实际场景进行考虑。

首先需要确定哪些列会被频繁地用作查询条件,然后根据单列查询还是复合查询的情况选择单列索引或复合索引。

还需要根据查询的频率、数据的分布情况等因素设计合适的索引类型,如 B-Tree 索引、哈希索引、全文索引、唯一索引等等。

在项目中如何查看一个索引的使用情况?

可以使用 MySQL 的慢查询日志功能进行查看。

慢查询日志会记录查询时间超过阈值的查询语句和对应的执行时间。

通过分析慢查询日志可以发现哪些查询没有使用索引,从而进行索引的调优。

如何在项目中使用索引来提高查询效率?

可以通过使用 EXPLAIN 关键字来查看查询执行计划,分析查询是否使用了索引。

如果查询没有使用索引,可以通过优化查询语句、增加索引、减少数据的扫描范围等方式来提高查询效率。

如果查询已经使用了索引,可考虑使用联合索引或优化查询次序等方式进一步提高查询效率

在一个高并发的项目中如何避免索引失效?

可以通过合理设置缓存,减少数据库访问;

通过分库分表等方式降低单库单表的访问压力;

实时监控数据库的性能指标,及时发现和解决性能问题;

合理设置索引和查询语句,避免全表扫描等操作;

通过数据库水平和垂直扩展等方式提高数据库的负载能力。

mysql数据库查询a,b两个字段时,应该建立a索引,还是b索引,还是ab索引,还是ba索引呢

如果查询条件只涉及a字段,那么建立a索引会更优;

如果只涉及b字段,则建立b索引更好。

如果查询条件同时涉及a和b两个字段,并且这两个字段的值的组合具有唯一性,那么建立联合索引(ab索引)可能是最好的选择。

但是,如果a和b的值分布不均衡,那么建立单独的索引可能会更好。

ab索引和ba索引有什么区别吗?

在关系型数据库中,建立联合索引时,ab索引和ba索引实际上是等效的。

也就是说,无论是用(ab)还是用(ba)作为联合索引字段的顺序,查询优化器都会使用相同的索引来执行相应的查询操作,并且这两个索引的性能也不会有太大区别。

它们的区别在于索引的生成方式和具体使用场景

猜你喜欢

转载自blog.csdn.net/Zhousan0125/article/details/130624775