什么是聚簇索引和非聚簇索引?
(重点在于叶子节点存储上的差异,个数,应用场景) 聚簇索引:
- 数据和索引存储在一起,
- 叶子节点存储的是数据行,(非叶子节点存储的是索引键值指向子节点(即下一级页面)的指针)
- 聚簇索引必须有,而且只能有一个
非聚簇索引:
- 数据和索引分开存储,
- 叶子节点存储的是索引键的值和指向数据行的指针(如行ID或行位置),(存储的是索引键值和指向子节点(即下一级页面)的指针),查询数据时一般需要进行回表查询。
- 非聚簇索引可以有多个。
各自应用场景?
聚簇索引适用于范围查询和排序;非聚簇索引适用于快速查找特定列的数据。
追问:为什么聚簇索引适用于范围查询和排序;非聚簇索引适用于快速查找特定列数据的场景?
聚簇索引: 由于数据行是按照索引键的顺序存储的,所以对于范围查询和排序操作,数据库可以顺序读取数据,这比随机访问数据行要快得多。这种物理存储方式减少了磁盘I/O,提高了查询效率。
非聚簇索引: 对于需要快速定位特定数据行的查询,非聚簇索引提供了一种快速访问机制。数据库可以通过索引键快速定位到数据行的位置,而不需要扫描整个表或使用顺序读取的方式。
追问:聚簇索引的选取规则?
- 一般主键作为聚簇索引
- 如果主键不存在,将使用第一个唯一(UNIQUE)索引作为聚集索引
- 如果表没有聚簇索引也没有唯一主键,则InnoDB会自动生成一个rowid作为隐藏的聚簇索引
追问:你上面提到的回表查询,请你解释一下?
回表查询是非聚簇索引查询数据的方式,因为非聚簇索引的叶子节点存储的是数据行的主键或者索引列,查询时需要根据这个主键或索引列来使用聚簇索引查询到数据行,这个叫做回表查询!
追问:非聚簇索引一定会进行回表查询吗?
不一定,例如:覆盖索引。 覆盖索引就是查询的数据已经包括在索引中,就可以直接返回数据而不需要再进行回表查询!
此外,在实际的操作中我们也可以使用explain命令来分析sql的执行计划,输出结果中Extra列中包含Using index,这表明查询使用了覆盖索引,不需要回表查询,如果Extra列中包含Using where,这意味着查询在索引中进行了条件过滤,但仍然需要回表查询!
追问:你上面提到的覆盖索引有哪些优点呢?
- 减少I/O次数:
- 提到查询效率
- 减少内存占用:因为只需要读取索引页而不是表数据页,减少了内存占用