当前位置: 代码网 > it编程>数据库>Mysql > MySQL索引选择与失效场景全解析

MySQL索引选择与失效场景全解析

2025年06月19日 Mysql 我要评论
一、适合建立索引的字段特征1.1 高选择性的字段选择性公式:选择性 = 不重复的值数量(distinct) / 总记录数选择性越接近1,索引效果越好示例分析:-- 查看字段选择性select co

一、适合建立索引的字段特征

1.1 高选择性的字段

选择性公式

选择性 = 不重复的值数量(distinct) / 总记录数

选择性越接近1,索引效果越好

示例分析

-- 查看字段选择性
select 
  count(distinct gender)/count(*) as gender_selectivity,
  count(distinct phone)/count(*) as phone_selectivity
from users;

1.2 常用查询条件的字段

查询类型索引效果示例
where条件★★★where user_id = 1001
join条件★★★on a.order_id = b.id
排序字段★★order by create_time desc
分组字段★★group by department

1.3 具体推荐场景

1.3.1 应当建索引的字段

  • 主键和外键字段(自动创建)
  • 高频查询的where条件字段
  • 多表join的关联字段
  • 排序和分组字段(特别是组合排序)
  • 区分度高的状态字段(如订单状态)

1.3.2 数值类型优先

-- 好的索引字段
alter table products add index idx_category_id (category_id);  -- 整型
alter table users add index idx_phone (phone);  -- 定长字符串

-- 较差的索引选择
alter table logs add index idx_content (content(255));  -- 长文本前缀索引

二、索引失效的8大常见场景

2.1 违反最左前缀原则

联合索引结构示例

alter table orders add index idx_user_status (user_id, status);

失效案例

-- 有效使用索引
explain select * from orders where user_id = 1001 and status = 1;

-- 部分失效(只用到了user_id)
explain select * from orders where user_id = 1001;

-- 完全失效(跳过了user_id)
explain select * from orders where status = 1;

2.2 对索引列使用函数或运算

失效示例

-- 索引失效
explain select * from users where date(create_time) = '2023-01-01';
explain select * from products where price + 100 > 500;

-- 优化方案
explain select * from users 
where create_time between '2023-01-01 00:00:00' and '2023-01-01 23:59:59';

2.3 隐式类型转换

常见陷阱

-- phone字段是varchar类型
explain select * from users where phone = 13800138000;  -- 失效
explain select * from users where phone = '13800138000';  -- 有效

-- 枚举值比较
explain select * from orders where status = '1';  -- 可能失效
explain select * from orders where status = 1;    -- 有效

2.4 使用不等于(!=或<>)

失效分析

-- 索引失效
explain select * from users where age != 30;

-- 优化方案(范围查询+union)
explain select * from users where age < 30 
union all 
select * from users where age > 30;

2.5 like以通配符开头

对比示例

-- 索引失效
explain select * from users where name like '%张%';

-- 索引有效(前缀匹配)
explain select * from users where name like '张%';

-- 特殊优化方案(全文索引)
alter table users add fulltext index ft_idx_name (name);
explain select * from users where match(name) against('张*' in boolean mode);

2.6 or条件使用不当

失效场景

-- 索引失效(其中一个条件无索引)
explain select * from users where user_id = 1001 or register_ip = '192.168.1.1';

-- 优化方案
explain select * from users where user_id = 1001
union all
select * from users where register_ip = '192.168.1.1' and user_id != 1001;

2.7 数据分布不均匀

案例演示

-- 当status=1占90%数据时
explain select * from orders where status = 1;  -- 可能全表扫描

-- 查看数据分布
select status, count(*) from orders group by status;

2.8 索引列参与is null判断

特殊情况

-- mysql 5.7+可以走索引
explain select * from users where phone is null;

-- 通常需要结合其他条件
explain select * from users where phone is null and create_time > '2023-01-01';

三、高级索引失效场景

3.1 索引合并导致的性能问题

-- 可能不如预期高效
explain select * from users 
where username = 'admin' or email = 'admin@example.com';

-- 优化方案
create index idx_username_email on users(username, email);

3.2 范围查询后的索引失效

-- 只有user_id和status能用索引,age失效
explain select * from orders 
where user_id = 1001 and status > 0 and age = 30;

-- 优化索引顺序
alter table orders add index idx_user_age_status (user_id, age, status);

3.3 不同字符集比较

-- 不同字符集比较导致失效
explain select * from users u join logs l 
on u.username = l.operator 
where u.charset = 'utf8mb4' and l.charset = 'latin1';

四、索引使用最佳实践

4.1 索引设计黄金法则

三星索引原则

  • 一星:where条件列是索引前缀
  • 二星:order by/group by列在索引中
  • 三星:select列被索引覆盖

索引维护成本

  • 写操作需要更新索引
  • 每个表最佳索引数通常为3-5个

4.2 实战案例解析

电商系统优化

-- 原始查询
select product_id, product_name, price 
from products 
where category_id = 5 
and status = 1 
and stock > 0 
order by sales_volume desc 
limit 20;

-- 优化方案
alter table products add index idx_cat_status_stock_sales 
(category_id, status, stock, sales_volume desc);

4.3 监控与调优工具

索引使用分析

-- 查看未使用的索引
select * from sys.schema_unused_indexes;

-- 索引统计信息
show index from products;

-- 查询性能分析
explain analyze select * from orders where user_id = 1001;

五、mysql 8.0索引新特性

5.1 倒序索引

alter table orders add index idx_create_time (create_time desc);

5.2 隐藏索引

-- 测试删除索引的影响
alter table users alter index idx_email invisible;
alter table users alter index idx_email visible;

5.3 函数索引

-- 对json字段建立索引
alter table products add index idx_price_data ((cast(price_data->'$.price' as decimal(10,2))));

六、总结与决策流程图

6.1 索引创建决策流程

6.2 索引失效排查清单

  • 检查explain执行计划
  • 验证sql是否遵循最左前缀原则
  • 检查是否有隐式类型转换
  • 排查是否使用了函数或运算
  • 分析数据分布情况
  • 确认字符集和排序规则一致性

通过系统性地理解索引适用场景和失效原理,可以显著提升数据库查询性能。实际应用中应当结合业务特点和数据分布,定期审查索引效果,避免过度索引和索引滥用。

以上就是mysql索引选择与失效场景全解析的详细内容,更多关于mysql索引选择与失效的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com