数据库索引使用时机---适合建立、不适合建立、索引失效总结

适合建立索引的情况

1.字段的数值有唯一性的限制
2.频繁作为WHERE 查询条件的字段
3.经常GROUP BY和ORDER BY的列
4.UPDATE、DELETE的WHERE条件列
5.DISTINCT字段需要创建索引
6.多表JOIN连接操作时,创建索引注意事项
7.使用列的类型小的创建索引
8.使用字符串前缀创建索引
9.区分度高(散列性高)的列适合作为索引
10.使用最频繁的列放到联合索引的左侧
11.在多个字段都要创建索引的情况下,联合索引优于单值索引

不适合建立索引的情况

1.在where中使用不到的字段,不要设置索引
2.数据量小的表最好不要使用索引
3.有大量重复数据的列上不要建立索引
4.避免对经常更新的表创建过多的索引
5.不建议用无序的值作为索引
6.删除不再使用或者很少使用的索引
7.不要定义冗余或重复的索引

索引失效的情况

1.全值匹配我最爱
2.最佳左前缀法则
3.主键插入顺序
4.计算、函数、类型转换(自动或手动导致索引失效
5.类型转换导致索引失效
6.范围条件右边的列索引失效
7.不等于(=或者<)索引失效
8.is nul可以使用索引, is not nul无法使用索引
9.likel以通配符%开头索引失效
10.OR前后存在非索引的列,索引失效
11.数据库和表的字符集统一使用utf8mb4
12.练习及一般性建议

### MySQL 中 GROUP BY 导致索引失效的原因 在 MySQL 的查询过程中,`GROUP BY` 是一种常见的聚合操作方式。然而,在某些情况下,`GROUP BY` 可能会导致索引失效,从而影响查询性能。以下是可能导致 `GROUP BY` 索引失效的主要原因: #### 1. **未遵循最左前缀原则** 如果定义的复合索引未能满足最左前缀原则,则可能会导致索引无法被有效利用。例如,假设有一个复合索引 `(col1, col2)`,而查询条件仅涉及 `col2` 或者 `GROUP BY` 子句中的列顺序符合索引定义的顺序,那么该索引可能会被使用[^1]。 #### 2. **隐式的类型转换** 当查询条件或 `GROUP BY` 列涉及到隐式类型转换时,MySQL 将无法直接使用索引。例如,字符串与数值之间的自动转换或者日期时间格式化等问题都可能导致索引失效[^3]。 #### 3. **使用函数或表达式** 在 `GROUP BY` 子句中应用任何函数(如 `UPPER()`、`LOWER()`)、算术运算或其他复杂表达式都会使索引失效。这是因为 MySQL 需要计算这些表达式的值后再进行分组操作,而是基于原始存储的数据[^3]。 #### 4. **数据分布特性** 即使存在适合索引,但如果表内的数据分布非常稀疏或者重复度极低,MySQL 查询优化器也可能决定放弃使用索引转而采用全表扫描的方式完成分组操作,因为在这种情形下全表扫描反而更快[^1]。 --- ### 解决方案 针对以上提到的各种情况,可以采取以下措施来改善由 `GROUP BY` 引起的索引失效问题: #### 1. **确保符合最左前缀原则** 重新设计查询以充分利用已有的复合索引,并严格按照其定义次序指定过滤条件以及分组依据。如果当前索引适合现有需求,则应考虑创建新的更适合特定查询模式的索引[^1]。 #### 2. **避免必要的类型转换** 保持查询字段与其对应数据库列之间的一致性非常重要。尽量避免让 MySQL 执行额外的类型推断工作;对于日期范围查找等情况尤其如此——应当始终传递正确格式化的常量而非依赖内置函数来进行解析[^5]。 #### 3. **移除函数调用** 修改应用程序逻辑使得可以直接引用未经修饰的基础列名作为 `GROUP BY` 参数的一部分,而附加任何形式的操作符或方法封装[^3]。 #### 4. **强制使用索引提示** 虽然一般建议信任 MySQL 自己的选择机制,但在特殊场景下确实有必要的话也可以显式地告诉它应该优先选用哪个具体索引(`FORCE INDEX`) 来加速目标查询过程[^1]。 #### 5. **升级到更高版本并注意行为差异** 同版本间可能存在兼容性和实现细节上的区别,比如从 MySQL 5.6 升级至 5.7 后发现原本正常工作的嵌套子查询加上外部层面上施加了另一个 `GROUP BY` 结果却发生了变化。此时需查阅官方文档了解新旧版间的改动点并通过适当调整SQL语法结构规避此类风险[^4]。 ```sql -- 示例:解决 MySQL 5.7 版本中 ORDER BY 和 GROUP BY 失效的问题 SELECT * FROM ( SELECT *, ROW_NUMBER() OVER(PARTITION BY sale_code ORDER BY data_month DESC) AS rn FROM risk ) a WHERE a.rn = 1; ``` 此代码片段展示了如何借助窗口函数替代传统嵌套查询形式达到相同效果的同时还能更好地控制排序规则的应用时机--- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_WAWA鱼_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值