面试题答案
一键面试索引创建原则
- 选择合适的列:
- 为经常出现在
WHERE
子句、JOIN
子句中的列创建索引。例如,在SELECT * FROM users WHERE age > 30;
中,age
列适合创建索引。 - 避免为低基数(即重复值很多)的列创建索引,如性别列(只有男、女两种值),这样的索引通常不会带来显著性能提升,反而增加存储和维护成本。
- 为经常出现在
- 前缀索引:
对于较长的字符串列,使用前缀索引。例如,对于一个很长的
description
列,可以创建CREATE INDEX idx_description ON table_name(description(10));
,这里的10
表示取前10个字符创建索引,这样能减少索引存储空间,同时仍能提高查询性能。
复合索引设计技巧
- 最左前缀原则:
复合索引的列顺序很重要,要按照最常使用的查询条件顺序排列。例如,对于查询
SELECT * FROM orders WHERE status = 'completed' AND customer_id = 123;
,应创建复合索引CREATE INDEX idx_status_customer ON orders(status, customer_id);
,因为查询会先根据status
过滤,再根据customer_id
进一步筛选。 - 避免冗余索引:
不要创建包含已有索引前缀的复合索引。例如,如果已经有了
CREATE INDEX idx_status ON orders(status);
,就没必要再创建CREATE INDEX idx_status_customer ON orders(status, customer_id);
(除非有特殊的查询需求依赖这个更复杂的索引),因为前者已经覆盖了最左前缀部分,冗余索引会增加存储和维护成本。
根据查询模式调整索引结构提升性能
- 覆盖索引:
如果查询只涉及部分列,尽量创建覆盖索引,即索引包含查询所需的所有列。例如,
SELECT user_name, email FROM users WHERE user_type = 'admin';
,可以创建CREATE INDEX idx_user_type_name_email ON users(user_type, user_name, email);
,这样MySQL可以直接从索引中获取数据,而无需回表操作,大大提高查询性能。 - 适应范围查询:
对于范围查询(如
BETWEEN
、>
、<
等),索引设计要考虑到后续列的使用。在复合索引中,范围查询列之后的列在查询时无法利用索引的全部优势。例如,CREATE INDEX idx_age_salary ON employees(age, salary);
,如果查询SELECT * FROM employees WHERE age > 30 AND salary > 50000;
,salary
列无法完全利用索引,因为age
列范围查询后,索引的有序性被破坏。此时,可以考虑对salary
列单独创建索引或者调整查询逻辑以更好利用索引。 - 分析查询日志: 通过分析MySQL的查询日志(如慢查询日志),找出频繁执行且性能不佳的查询,针对这些查询优化索引结构。例如,如果发现某个复杂的多表连接查询经常很慢,检查连接条件和过滤条件,为相关列创建合适的索引。