面试题答案
一键面试索引失效场景分析
LIKE '%tech%'
部分:在department
字段使用LIKE '%tech%'
,这属于模糊匹配,且通配符在开头。数据库索引无法在这种情况下有效利用,因为索引是基于有序数据结构,无法快速定位以tech
结尾的数据,导致全表扫描,索引失效。- 联合索引使用问题:虽然
department
和salary
分别建有索引,但该查询语句中,由于department
字段索引失效,无法利用联合索引优化,即使salary
字段条件本身可使用索引,也会因前面的条件导致整体索引失效。
EXPLAIN
分析执行计划
通过EXPLAIN SELECT * FROM employees WHERE department LIKE '%tech%' AND salary > 5000;
,可能看到执行计划如下:
id
:表示查询的序列号。select_type
:通常为SIMPLE
,表示简单查询。table
:显示操作的表为employees
。partitions
:如果表是分区表,会显示相关分区信息,否则为NULL
。type
:可能为ALL
,表示全表扫描,因为索引失效。possible_keys
:显示可能使用的索引,这里会列出department
和salary
索引。key
:为NULL
,表示实际没有使用索引。key_len
:NULL
。ref
:NULL
。rows
:表示预估需要扫描的行数,可能是全表行数。filtered
:预估满足条件的行占总行数的百分比。
优化方案
改写查询语句
- 改变
LIKE
匹配方式:如果业务允许,将LIKE '%tech%'
改为LIKE 'tech%'
,这样可以利用department
字段的索引。例如:SELECT * FROM employees WHERE department LIKE 'tech%' AND salary > 5000;
- 使用全文索引:如果模糊匹配必须以通配符开头,可以考虑使用全文索引。首先,修改表结构添加全文索引:
ALTER TABLE employees ADD FULLTEXT(department);
然后使用MATCH AGAINST
语法查询:
SELECT * FROM employees WHERE MATCH(department) AGAINST('tech' IN NATURAL LANGUAGE MODE) AND salary > 5000;
调整表结构和索引策略
- 联合索引:如果经常以
department
和salary
同时作为查询条件,可以创建联合索引。先删除原有的两个单索引(如果不需要单索引查询):
DROP INDEX department_idx ON employees;
DROP INDEX salary_idx ON employees;
然后创建联合索引:
CREATE INDEX combined_idx ON employees(department, salary);
这样在查询时,如果department
字段条件可使用索引(如LIKE 'tech%'
),则可以利用联合索引对salary
字段条件进一步筛选,提高查询性能。但要注意联合索引的最左前缀原则。
2. 冗余字段和索引:如果某些查询非常频繁,可以考虑添加冗余字段。例如,添加一个department_short
字段,存储department
字段的短摘要信息,并且针对这个新字段创建合适的索引,用于满足特定的查询需求,避免对原字段进行复杂的模糊匹配导致索引失效。