回答
索引是一把双刃剑,一方面它可以提升查询效率;再者 DML 操作需维护索引,产生额外性能开销。故设计索引时需结合业务场景,从索引类型、字段区分度、覆盖索引、联合索引、前缀索引等方面综合考虑。
一、基本原则
- 选择合适的列进行索引
- 频繁作为查询条件的列,索引应添加在
where
子句中频繁使用的列上。 - 用于连接的列,对于多表连接查询,索引应添加在连接条件的列上。
- 用于排序的列,为
ORDER BY
子句的列添加索引,保证查询结果集天然有序。 - 用于分组的列,索引将数据按照某种顺序进行存储从而加快索引,为
GROUP BY
子句的列添加索引能加速分组查询。 - 索引的区别度
- 高选择性,选择性高的列(唯一值较多)适合作为索引,因为它们能有效减少索引扫描的行数。
- 低选择性,选择性低的列(重复值较多)索引效果不佳如性别、职业状态、婚姻状态等,因为它们对查询性能的提升有限。
二、索引类型选择
- B+ 树索引
InnoDB 引擎默认的索引类型,适用于大多数查询场景,如精确查找、范围查询和排序。
- 哈希索引
哈希索引适用于唯一查找场景,不适合范围查询。
- 全文索引
全文索引用于全文搜索,适合大文本字段的查找。
- 空间索引
空间索引主要用于地理空间数据索引。
三、覆盖索引和联合索引
- 覆盖索引
将一个查询所有涉及的列都加上索引,从而避免回表。覆盖索引能显著提升查询性能。
-- 覆盖索引
CREATE INDEX idx_employee_name_age ON t_employee(name, age);
-- 覆盖索引查询(idx_employee_name_age)
SELECT name, age FROM t_employee WHERE name = 'Bob';
- 联合索引
对于where
子句包含多个列,可以为多个列创建联合索引。创建联合索引时考虑"最左前缀原则"。根据查询字段使用的频率和过滤条件排列,将最常用的列放在前面。
SELECT id, name, age, contact_phone FROM t_employee WHERE name = 'Bob' and age = 20;
- 前缀索引
为长文本字段加索引时(如 VARCHAR 字段),创建前缀索引以节省空间和提高性能。
CREATE INDEX idx_name_prefix ON t_employee (name(10));
- 唯一索引
对于需要唯一约束的业务场景,为列值创建**唯一索引,**从而保证列值的唯一。
CREATE UNIQUE INDEX udx_employee_phone ON t_employee(contact_phone);
四、避免冗余索引
- 冗余索引
多个索引覆盖相同列或部分相同列时,会造成冗余。如索引(name, age)
和索引(name)
是冗余的。再者,过多的索引会增加插入、更新以及删除操作的开销,因为每次数据的修改都需要维护索引。