-
查询条件未使用索引列
描述:查询条件没有涉及索引列时,MySQL 会直接执行全表扫描。
示例:
sqlSELECT * FROM users WHERE non_indexed_column = 'example';
解决方法:在需要频繁查询的列上创建索引。
-
查询条件对索引列使用了函数或表达式
描述:对索引列进行函数或表达式操作会导致索引失效。
示例:
sqlSELECT * FROM users WHERE LEFT(name, 3) = 'Ali';
解决方法:避免对索引列进行变换,改为:
SELECT * FROM users WHERE name LIKE 'Ali%';
-
数据类型不一致引发隐式类型转换
描述:当查询条件值的类型与索引列类型不一致时,MySQL 会进行隐式类型转换。
示例:
sqlSELECT * FROM users WHERE phone = 1234567890; -- phone 是 VARCHAR
解决方法:确保类型一致:
SELECT * FROM users WHERE phone = '1234567890';
-
联合索引使用时的范围查询阻断
描述:在联合索引中,如果某列的范围查询中断了索引的有序性,后续列的索引无法生效。
示例:
sqlSELECT * FROM users WHERE name = 'Alice' AND age > 30 AND city = 'New York';
解决方法:调整查询逻辑或单独为后续列创建索引。
-
使用 OR 条件
描述:如果 OR 条件中有字段未使用索引,会导致整体索引失效。
示例:
sqlSELECT * FROM users WHERE name = 'Alice' OR age = 30;
解决方法:拆分查询,用 UNION 替代:
sqlSELECT * FROM users WHERE name = 'Alice' UNION SELECT * FROM users WHERE age = 30;
-
前置通配符的模糊查询
描述:LIKE 查询中使用前置通配符 % 时,无法利用索引。
示例:
sqlSELECT * FROM users WHERE name LIKE '%Alice';
解决方法:替换为后置通配符 LIKE 'Alice%';使用全文索引:
ALTER TABLE users ADD FULLTEXT(name);
sqlSELECT * FROM users WHERE MATCH(name) AGAINST('Alice');
-
不等值查询
描述:不等值操作符(!=、<>)通常会导致索引失效。
示例:
sqlSELECT * FROM users WHERE age != 30;
解决方法:改写为范围查询:
SELECT * FROM users WHERE age < 30 OR age > 30;
-
IN 子句列表过长
描述:IN 子句中参数过多时,索引可能失效。
示例:
sqlSELECT * FROM users WHERE id IN (1, 2, ..., 10000);
解决方法:分批查询或控制 IN 参数数量:
SELECT * FROM users WHERE id BETWEEN 1 AND 5000;
-
NULL 查询
描述:某些情况下对 NULL 值的查询可能导致索引失效。
示例:
sqlSELECT * FROM users WHERE email IS NULL;
解决方法:避免使用 NULL,改为特定占位值。
-
ORDER BY 和 GROUP BY 不符合索引顺序
描述:排序或分组字段与索引顺序不匹配时,索引无法生效。
示例:
sqlSELECT * FROM users ORDER BY age, name; -- 索引顺序为(name, age)
解决方法:调整查询或索引顺序一致。
-
索引列未覆盖查询字段
描述:查询中包含未索引的字段,可能导致回表或索引失效。
示例:
sqlSELECT age FROM users WHERE name = 'Alice';
解决方法:创建覆盖索引:
ALTER TABLE users ADD INDEX(name, age);
-
表统计信息过期
描述:表的统计信息不准确时,MySQL 优化器可能错误选择全表扫描。
解决方法:定期更新统计信息:ANALYZE TABLE users;
-
数据分布不均
描述:某些列的数据分布高度不均匀,可能导致索引失效。
示例:
sqlSELECT * FROM users WHERE gender = 'M'; -- gender 列 90% 的值相同
解决方法:优化查询字段或调整数据分布。
-
子查询未优化
描述:子查询结果集过大时,索引失效。
示例:
sqlSELECT * FROM users WHERE id IN (SELECT user_id FROM orders WHERE total > 100);
解决方法:改为 JOIN 查询:
SELECT u.* FROM users u JOIN orders o ON u.id = o.user_id WHERE o.total > 100;
-
锁机制干扰(间隙锁)
描述:间隙锁可能阻止索引的高效使用。
示例:
sqlSELECT * FROM users WHERE id BETWEEN 10 AND 20 FOR UPDATE;
解决方法:降低事务隔离级别至 Read Committed。
-
索引被动态调整
描述:MySQL 优化器动态调整索引,可能选择非最佳索引或直接全表扫描。
解决方法:使用 FORCE INDEX 强制指定索引:
SELECT * FROM users FORCE INDEX (idx_name) WHERE name = 'Alice';
-
聚合函数未走索引
描述:使用聚合函数(如 COUNT、SUM)时,索引可能无法被利用。
示例:
sqlSELECT COUNT(*) FROM users WHERE age > 30;
解决方法:利用覆盖索引:
ALTER TABLE users ADD INDEX(age);
-
使用了非等值 JOIN
描述:非等值连接可能导致索引失效。
示例:
sqlSELECT * FROM users u JOIN orders o ON u.id > o.user_id;
解决方法:优化连接条件,尽量使用等值连接。
-
小表全表扫描替代索引扫描
描述:对于非常小的表,MySQL 优化器可能选择全表扫描而非索引。
示例:
sqlSELECT * FROM small_table WHERE id = 1;
解决方法:无需优化,小表全表扫描的代价通常可以忽略。
-
分区表查询不走全局索引
描述:分区表的查询条件未覆盖分区键时,全局索引可能无法生效。
示例:
sqlSELECT * FROM partitioned_users WHERE city = 'New York';
解决方法:在分区键上创建局部索引。
面试——MySql索引什么场景下会失效
你知道烟火吗2024-12-06 17:15
相关推荐
测试界萧萧3 小时前
15:00面试,15:08就出来了,问的问题有点变态。。。先生先生3933 小时前
Java小公司面试小天努力学java3 小时前
【面试系列】深入浅出 Springdengjiayue4 小时前
MySQL 查询大偏移量(LIMIT)问题分析言之。4 小时前
【MySQL】在MySQL中如何定位慢查询?Suwg2094 小时前
【MySQL】踩坑笔记——保存带有换行符等特殊字符的数据,需要进行转义保存PittDing4 小时前
【更新】Docker新手入门教程2:在Windows系统通过compose创建多个mysql镜像并配置应用-$_$-4 小时前
【LeetCode 面试经典150题】详细题解之哈希表篇m0_672449605 小时前
前后端分离(前端删除数据库数据)正在绘制中5 小时前
Java重要面试名词整理(八):RabbitMQ