Mysql面试题以及答案-索引

时间:2024-03-24 07:17:31

2.1、索引的几种类型或分类?

物理结构上可以分为聚集索引和非聚集索引

        简单来说,聚集索引就是基于主键创建的索引,除了主键索引以外的其他索引,称为非聚集索引,也叫做二级索引。

        由于在InnoDB引擎里面,一张表的数据对应的物理文件本身就是按照B+树来组织的一种索引结构,而聚集索引就是按照每张表的主键来构建一颗B+树,然后叶子节点里面存储了这个表的每一行数据记录。
        所以基于InnoDB这样的特性,聚集索引并不仅仅是一种索引类型,还代表着一种数据的存储方式。
        同时也意味着每个表里面必须要有一个主键,如果没有主键,InnoDB会默认选择或者添加一个隐藏列作为主键索引来存储这个表的数据行。一般情况是建议使用自增id作为主键,这样的话id本身具有连续性使得对应的数据也会按照顺序存储在磁盘上,写入性能和检索性能都很高。否则,如果使用uuid这种随机id,那么在频繁插入数据的时候,就会导致随机磁盘IO,从而导致性能较低。
        需要注意的是,InnoDB里面只能存在一个聚集索引,原因很简单,如果存在多个聚集索引,那么意味着这个表里面的数据存在多个副本,造成磁盘空间的浪费,以及数据维护的困难。
由于在InnoDB里面,主键索引表示的是一种数据存储结构,所以如果是基于非聚集索引来查询一条完整的记录,最终还是需要访问主键索引来检索。

从应用上可以划分为一下几类

主键索引:特殊的唯一索引,也成聚簇索引,不允许有空值,并由数据库帮我们自动创建;

唯一索引:索引列中的值必须是唯一的,但是允许为空值。通过 ALTER TABLE table_name ADD UNIQUE index_name (column) 创建;

普通索引:MySQL 中的基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值,纯粹为了提高查询效率。通过 ALTER TABLE table_name ADD INDEX index_name (column) 创建;

组合索引:组合表中多个字段创建的索引,遵守最左前缀匹配规则;

全文索引:只有在 MyISAM 引擎上才能使用,同时只支持 CHAR、VARCHAR、TEXT 类型字段上使用。

在设计数据库索引时,应遵循一些基本原则以确保索引具有高效的性能和实用性。以下是一些关键的索引设计原则:

  1. 选择性高的字段

    • 优先为那些具有高选择性的字段创建索引。选择性是指不同值的数量占总行数的比例。具有高唯一值的列(如主键)通常是很好的索引候选。
  2. 根据查询优化

    • 索引应基于最常用的查询操作进行建立,考虑WHERE子句中的列、JOIN操作中的列以及ORDER BY和GROUP BY子句中的列。
  3. 避免冗余索引

    • 避免创建重复和冗余的索引。如果一个列已经是另一个复合索引的前缀,则通常不需要为该列单独创建索引。
  4. 复合索引设计

    • 当查询条件中经常包含多个列时,考虑创建复合索引。在创建复合索引时,将选择性最高的列放在最前面。
  5. 索引维护

    • 随着数据的变化,索引会发生碎片化,应定期进行索引维护,如重建或重新组织索引。
  6. 限制索引数量

    • 过多的索引会增加插入、更新和删除操作的开销,因为这些操作都需要维护索引。因此,避免在不经常用于查询的列上建立索引。
  7. 考虑数据类型和大小

    • 较小的数据类型通常更适合索引,因为它们在磁盘上占用更少的空间,可以减少I/O操作。例如,INT比CHAR或VARCHAR更适合索引。
  8. 使用前缀索引

    • 对于文本字段(如VARCHAR、TEXT),如果全文索引不适用或不必要,可以使用前缀索引以节约空间,并提升效率。
  9. 考虑索引的存储成本

    • 索引虽然可以提升查询性能,但也占用存储空间。需要权衡索引带来的性能提升和额外的存储成本。
  10. 测试和分析

    • 使用EXPLAIN或其他工具分析查询计划,验证索引的实际效果,并根据实际的查询负载对索引策略进行调整。
  11. 适当反范式化

    • 在某些情况下,为了提高查询性能,可以适当反范式化数据库设计,并创建冗余的数据和索引。
  12. 避免对频繁修改的列进行索引

    • 如果某个列的数据频繁更新,每次更新都需要维护索引,可能会降低整体性能。

正确的索引设计需要综合考虑表的数据量、数据分布、数据访问模式(如查询、插入、更新的频率)以及应用的具体业务需求。设计索引的过程往往是一个不断调整和优化的过程。

2.2、为什么 B+ 树比 B 树更适合应用于数据库索引?

MySQL数据库索引通常使用的是B+树,而不是B树,这是因为B+树相比于B树具有一些特性使其更适合作为数据库索引的数据结构。下面列出了B+树相比于B树的几个优点:

  1. 查询性能稳定:在B+树中,所有的数据都存储在叶子节点,他们的高度是相同的,因此查询使用时间趋于一致。

  2. 叶子节点顺序访问:由于B+树的叶子节点之间是相互连接的,这使得顺序访问变得非常高效。这对于数据库中的范围查询特别重要,因为这些查询经常需要访问顺序排列的数据。

  3. 磁盘读写优化:B+树的非叶子节点不保存数据,只保存指向子节点的指针,这意味着相比于B树的同一高度,B+树可以有更多的分支,这样树的高度更低,查询时需要的磁盘I/O操作也就更少。

  4. 由于B+树的内部节点不存储实际的数据,只存储键值和子节点指针,这使得每个内部节点可以有更多的子节点。这种结构使得B+树可以更加紧凑,从而减少了树的高度,提高了空间利用率。

  5. 更好的删除性能:在B树中,删除操作可能会引起数据在父节点和子节点之间的移动,而在B+树中,数据只在叶子节点中移动,这通常会简化删除操作。

由于这些优点,B+树成为了数据库索引的首选数据结构。在实际的数据库系统中,例如MySQL的InnoDB存储引擎,使用B+树作为其主要索引(聚簇索引)和辅助索引的数据结构。

2.3、InnoDB 为何推荐使用自增主键?

InnoDB存储引擎推荐使用自增主键的原因主要与其索引结构和数据存储方式有关。InnoDB 使用聚簇索引(Clustered Index)来存储表中的数据,聚簇索引的特点是表中的数据按照主键的顺序存储在磁盘上。这种存储方式对于某些类型的查询和操作有显著的性能优势。以下是使用自增主键的几个主要原因:

  1. 插入性能:自增主键意味着新记录总是在索引的最后一个位置插入,这样的顺序插入减少了页的分裂和行移动,因为每次插入时不需要重新排序现有的数据,从而提高了插入操作的效率。

  2. 聚簇索引优势:在InnoDB中,聚簇索引包含了行的全部数据。如果主键是自增的,数据在磁盘上就是顺序存储的,这对于按照主键顺序访问行的查询非常高效,因为它们可以顺序读取磁盘上的数据块。

  3. 减少页分裂:非自增的主键(例如随机的GUID/UUID或者基于非自增字段的复合主键)可能导致中间插入,这样的操作会引起更多的页分裂,从而影响性能和空间利用效率。

  4. 避免外部碎片:自增主键可以减少数据的外部碎片,因为新数据总是添加到索引的末尾。

  5. 简化辅助索引结构:在InnoDB中,辅助索引(Secondary Index)包含对应的主键列作为指向聚簇索引记录的指针。如果主键比较简单(如自增的整数),辅助索引的大小也会相对较小。