两类索引
聚簇索引:
- 如果表设置了主键,主键就是聚簇索引
- 如果没有主键,默认第一个 NOT NULL,且 UNIQUE 的列作为聚簇索引
- 都没有,默认创建一个隐藏的 row_id 作为聚簇索引
InnoDB聚簇索引的叶子结点存储的是行记录(页结构,一个页包含多行数据)
InnoDB 有且仅有一个聚簇索引
普通索引:
- 也叫二级索引,非聚簇索引
- InnoDB普通索引叶子结点存储的是主键值(聚簇索引),MyISAM 普通索引存储的是记录指针
查找过程
聚簇索引
如果查询条件为主键(聚簇索引),只需扫描一次 B+树,即可定位到行数据
select * from user where id=1;
普通索引
如果查询条件为普通索引(非聚簇索引),并且查询数据 不只有 主键和索引列,则需要扫描两次 B+树
第一次扫描定位到聚簇索引的值,
第二次扫描通过聚簇索引找到行记录,获取到其他列数据。
select * from user where age=30;
这两次扫描就是回表查询
如果 只查找 主键与普通索引列,就直接从索引中取数据,不需要回表查询其他列数据
select id, age from user where age=30;
此时 explain 的 Extra 会显示 Using Index。
防止回表查询
建立联合索引
将被查询的字段,与主键建立联合索引
如实现:select id, age, name from user where age=10;
创建联合索引:
create index idx_age_name on user (age, name);
修改主键格式
比如用户帖子,主键格式可以是 用户唯一标识+压缩后的秒级时间戳+用户设备序号
这里压缩秒级时间戳可以设计为:
- 帖子发布时间减去系统初次发布时间,再进行36进制编码
这样设计可以利用数据库的 范围查询
查询某个用户的帖子的 SQL:
select * from post where postId between postId1 and postId2;
或者
select * from post where postId like “用户唯一标识%”
这样直接查询主键就可以避免回表,
随着帖子数量增加,还可以根据 postId 中的 userid 水平拆分