回答
索引是一把双刃剑,一方面它可以提升查询效率;再者 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)
是冗余的。再者,过多的索引会增加插入、更新以及删除操作的开销,因为每次数据的修改都需要维护索引。
五、避免索引失效
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。