在 MySQL 中,有些情况可能会导致索引失效,无法有效利用索引来加速查询。以下是一些常见的导致索引失效的情况:
一、不符合最左匹配原则
当查询条件不符合最左匹配原则时,索引可能会失效。例如:
SELECT * FROM users WHERE age = 30;
如果索引是(name, age),则 age 作为查询条件在最左边列之前,因此不能有效利用该索引。
二、使用了不支持索引的操作符
一些操作符会导致索引失效,例如:
范围查询:当查询中包含了范围查询(如 BETWEEN、<、>)但条件列未按索引顺序列出时,索引可能会失效。
SELECT * FROM users WHERE salary > 50000 AND age = 30;
函数或表达式:在查询条件中对索引列使用函数或表达式会导致索引失效。例如:
SELECT * FROM users WHERE YEAR(date_of_birth) = 1990;
这里 YEAR(date_of_birth) 使用了函数,会导致索引失效。
三、数据类型不匹配
如果查询条件的数据类型与索引列的数据类型不匹配,索引可能会失效。例如:
SELECT * FROM users WHERE id = '123';
如果 id 是整数类型,将整数与字符串进行比较可能导致索引失效。
四、使用 LIKE 操作符的不匹配
前缀通配符:LIKE 操作符中的前缀通配符(%)会使索引失效。例如:
SELECT * FROM users WHERE name LIKE '%Alice%';
在这种情况下,MySQL 无法使用索引来优化查询。
前缀匹配:如果 LIKE 的模式以固定字符开始(不以 % 开头),则可以利用索引。例如:
SELECT * FROM users WHERE name LIKE 'Alice%';
五、数据量过小
如果表的数据量非常小,数据库可能决定不使用索引,而是直接进行全表扫描,因为全表扫描可能更快。
六、不等于 <> 或 != 操作符
在某些情况下,使用不等于操作符可能导致索引失效,尤其是在涉及范围查询时。例如:
SELECT * FROM users WHERE age <> 30;
七、JOIN 操作中的索引选择
在 JOIN 操作中,如果条件列没有被正确地索引,或者索引选择不当,也可能导致索引失效。例如:
SELECT * FROM orders
JOIN customers ON orders.customer_id = customers.id
WHERE customers.name = 'Alice';
如果 orders 表的 customer_id 列没有索引,可能导致查询效率下降。
八、ORDER BY 与 GROUP BY 的顺序不一致
如果 ORDER BY 或 GROUP BY 的顺序与索引顺序不一致,可能会导致索引失效。
例 1:单列排序与索引顺序冲突
索引为 idx_name_age(name, age),但查询为:
SELECT * FROM users ORDER BY age;
失效原因:索引按 name 排序后,age 在索引中是二级顺序。若按 age 排序,需先扫描整个索引(或全表),再对 age 值排序,无法直接利用索引的有序性。
例2:多列排序顺序颠倒
索引为 idx_age_name(age, name),查询为:
SELECT * FROM users ORDER BY name, age;
失效原因:索引按 age 优先排序,而查询要求先按 name 排序。顺序颠倒导致索引无法直接用于排序,需额外排序操作。
例3:索引未覆盖查询列
示例:索引为 idx_age(age),查询为:
SELECT * FROM users ORDER BY age;
失效风险:若 SELECT * 包含非索引列(如 address),数据库需回表查询完整行数据。若回表成本高,优化器可能认为全表扫描+文件排序更高效,从而放弃索引。
九、更新或删除操作
在进行大量的更新或删除操作时,索引可能会变得不再有效。如果表中的数据发生变化,索引需要进行更新和维护,以确保其正确性。
十、总结
了解这些导致索引失效的情况有助于在设计数据库表和编写查询时做出更合适的选择,从而提高查询性能。
在实际应用中,结合具体的场景进行优化和测试,以确保索引的有效利用。
mysql 第5.5章 索引-什么情况下会导致索引失效