主键索引和普通索引的区别
问题
主键索引和普通索引的区别
我的回答
存储结构和数据访问方式
主键索引(聚簇索引)的数据存储方式是,索引和数据行是存储在一起的。具体来说,在InnoDB中,主键索引的B+树叶子节点存储的是整行数据。当你根据主键查询时,直接就能从索引树上获取到完整的数据行,一步到位。
而普通索引(二级索引/非聚簇索引)的B+树叶子节点存储的是索引列的值和对应的主键值,不包含其他列的数据。所以当你使用普通索引查询时,通常需要两步:先通过普通索引找到主键值,然后再通过主键值去主键索引中查找完整的数据行。这个过程叫做"回表"。
举个例子,假设有一个用户表,主键是id,还有name字段建了普通索引:
- 如果执行SELECT * FROM users WHERE id = 1,数据库直接从主键索引获取完整行数据。
- 如果执行SELECT * FROM users WHERE name = 'Tom',数据库先从name索引找到id值,再根据id去主键索引查找完整数据。
唯一性和约束
主键索引强制要求索引列的值是唯一的且不能为NULL。一个表只能有一个主键,因此也只能有一个主键索引。主键通常用来唯一标识一行数据。
普通索引没有唯一性的要求,可以有重复值,也可以包含NULL值(除非你专门创建了唯一索引或NOT NULL约束)。一个表可以有多个普通索引,用于加速不同条件的查询。
性能影响
查询性能:主键索引查询通常比普通索引快,因为不需要回表操作。特别是在大表上,回表可能带来显著的性能开销。
更新性能:主键值的更新成本较高,因为可能需要移动数据行(特别是当表按主键顺序物理存储时)。而普通索引的更新相对轻量,只需要更新索引结构。
插入性能:如果使用自增主键,插入性能会很好,因为新行总是添加到末尾。但如果使用随机值作为主键(如UUID),可能导致页分裂,影响性能。
对于范围查询和排序查询,聚簇索引通常更有效率,因为它避免了额外的寻址开销。非聚簇索引在使用覆盖索引进行查询时效率更高,因为它不需要读取完整的数据行。但是需要进行回表的操作,使用非聚簇索引效率比较低,因为需要进行额外的回表操作。