CC BY 4.0 (除特别声明或转载文章外)
一、索引
-
索引的定义:索引是一种数据结构(常见是 B+树,也有哈希索引等),存储了列的值和对应的记录位置。
-
主键索引:
在 InnoDB 这种常见的存储引擎里:表的数据本身就是按照主键索引组织的(聚簇索引,Clustered Index)。
叶子节点存放的是整行数据。
当你用主键索引查询时,数据库直接通过 B+ 树找到对应的叶子节点,就能直接拿到 整行数据。 无需再做额外查询。
-
普通索引:
普通索引的叶子节点存的不是整行数据,而是主键的值。
普通索引作条件时,查询数据时需要找到对应的主键的值,再通过主键的值查询整条数据,这个过程叫作回表。
-
联合索引:
联合索引是在多个列上建立的索引。
例如:
CREATE INDEX idx_user_name_age ON user(name, age);
这就是在
(name, age)
上建立的联合索引。 它会在 B+ 树 里,先按name
排序,如果name
相同,再按age
排序。走不走联合索引要看查询条件是否符合最左前缀原则。
比如
(name, age, gender)
联合索引:WHERE name = 'Tom' WHERE name = 'Tom' AND age = 18 WHERE name = 'Tom' AND age = 18 AND gender = 'M' WHERE name = 'Tom' AND gender = 'M' -- 也能用,但只用到 name 部分 WHERE age = 18 -- 没有从最左边的 name 开始 WHERE gender = 'M' -- 跳过前
联合索引通常比多个单列索引更高效,尤其是多条件查询时。
- 在
name
上有索引idx_name(name)
。 - 在
age
上有索引idx_age(age)
。
数据库的执行过程可能是:
- 通过
idx_name
找到所有name = 'Tom'
的记录(假设有 1000 条)。 - 再到表里逐条过滤
age = 25
。
或者用 索引合并:
- 用
idx_name
找出name = 'Tom'
的主键集合(1000 条)。 - 用
idx_age
找出age = 25
的主键集合(5000 条)。 - 取交集(最终几十条)。 👉 但这样要访问两棵索引树,效率相对差。
联合索引执行过程:
执行过程:
- B+树里已经按照
(name, age)
排序。 - 数据库能直接定位到
name = 'Tom' AND age = 25
的精确区间。 - 直接把结果返回(假设只有 3 条)。
👉 这时只用扫描极少的节点,比单列索引快很多。
- 在
-
覆盖索引:如果查询只需要索引里包含的字段,就不用回表,直接从索引拿数据,这叫覆盖索引。