2024-11-09
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://www.skjava.com/mianshi/baodian/detail/5539160506

回答

索引是一把双刃剑,一方面它可以提升查询效率;再者 DML 操作需维护索引,产生额外性能开销。故设计索引时需结合业务场景,从索引类型、字段区分度、覆盖索引、联合索引、前缀索引等方面综合考虑。

一、基本原则

  1. 选择合适的列进行索引
  2. 频繁作为查询条件的列,索引应添加在where子句中频繁使用的列上。
  3. 用于连接的列,对于多表连接查询,索引应添加在连接条件的列上。
  4. 用于排序的列,为ORDER BY子句的列添加索引,保证查询结果集天然有序。
  5. 用于分组的列,索引将数据按照某种顺序进行存储从而加快索引,为GROUP BY子句的列添加索引能加速分组查询。
  6. 索引的区别度
  7. 高选择性,选择性高的列(唯一值较多)适合作为索引,因为它们能有效减少索引扫描的行数。
  8. 低选择性,选择性低的列(重复值较多)索引效果不佳如性别、职业状态、婚姻状态等,因为它们对查询性能的提升有限。

二、索引类型选择

  1. B+ 树索引

InnoDB 引擎默认的索引类型,适用于大多数查询场景,如精确查找、范围查询和排序。

  1. 哈希索引

哈希索引适用于唯一查找场景,不适合范围查询。

  1. 全文索引

全文索引用于全文搜索,适合大文本字段的查找。

  1. 空间索引

空间索引主要用于地理空间数据索引。

三、覆盖索引和联合索引

  1. 覆盖索引

将一个查询所有涉及的列都加上索引,从而避免回表。覆盖索引能显著提升查询性能。

-- 覆盖索引
CREATE INDEX idx_employee_name_age ON t_employee(name, age);

-- 覆盖索引查询(idx_employee_name_age)
SELECT name, age FROM t_employee WHERE name = 'Bob';

非聚簇索引一定会回表吗?

  1. 联合索引

对于where子句包含多个列,可以为多个列创建联合索引。创建联合索引时考虑"最左前缀原则"。根据查询字段使用的频率和过滤条件排列,将最常用的列放在前面。

SELECT id, name, age, contact_phone FROM t_employee WHERE name = 'Bob' and age = 20;
  1. 前缀索引

为长文本字段加索引时(如 VARCHAR 字段),创建前缀索引以节省空间和提高性能。

CREATE INDEX idx_name_prefix ON t_employee (name(10));
  1. 唯一索引

对于需要唯一约束的业务场景,为列值创建**唯一索引,**从而保证列值的唯一。

CREATE UNIQUE INDEX udx_employee_phone ON t_employee(contact_phone);

四、避免冗余索引

  1. 冗余索引

多个索引覆盖相同列或部分相同列时,会造成冗余。如索引(name, age)和索引(name)是冗余的。再者,过多的索引会增加插入、更新以及删除操作的开销,因为每次数据的修改都需要维护索引。

五、避免索引失效

MySQL 索引失效的场景有哪些?

阅读全文