247期说说MySQL不走索引的场景

2021-07-14 12:17 Java最全面试题库

图片


# 引言


某个忙(mo)碌(yu)的下午,旁边的刘哥(老江湖,从业5年+)突然发出了一声叹息:“哎,mysql 出bug了,有索引不走”。


作为一个热心的人,我立即说到:“是不是,对索引字段做了函数操作”。


刘哥沉思了2秒,略有玩味的小眼神看了看我,慢慢说道:“温兄,常规的情况,对索引字段做函数操作,或者 字符串与数字比较造成的隐式转换,这次的SQL都不涉及”。


我一听顿时来了兴趣,略带兴奋的跟刘哥说:“刘哥,您发SQL,我也研究下”。

刘哥略有无奈的看了看我后,依旧把SQL发给了我:

SELECT * FROM oc_order oo JOIN orders_detail od ON oo.order_id = od.order_id

不过须臾(近20分钟),我便查明了原因,装作大师的模样,一字一句的说到:”这是,字符集隐式转换问题”


刘哥听后,百度了下,直拍大腿,“对对,怎么把这个给忘了”。


# 定位问题


1.首先执行explain,查看执行计划

explainSELECT * FROM oc_order oo JOIN orders_detail od ON oo.order_id = od.order_id

图片


确实被驱动表orders_detail 没走索引

第一个表就是驱动表,后边的都是被驱动表,会从驱动板取出数据作为参数,到被驱动表查询匹配的记录。


2. 查看被驱动表的索引

SHOW INDEX FROM  test.orders_detail;

图片


3.查看字段字符集

SELECT COLUMN_NAME, character_set_name, collation_name FROM INformation_schema.`COLUMNS` WHERE TABLE_NAME = 'oc_order'  AND COLUMN_NAME = 'order_id';

图片

SELECT COLUMN_NAME, character_set_name, collation_name FROM INformation_schema.`COLUMNS` WHERE TABLE_NAME = 'orders_detail'  AND COLUMN_NAME = 'order_id';

图片

# Mysql字符集说明


utf8m4是utf8超集,utf8,与utf8mb4会比较,utf8会转换为utf8mb4。


# 验证


调整SQL语句,将oc_orders的order_id强制转换为utf8。

explainSELECT * FROM oc_order oo JOIN orders_detail od ON CONVERT ( oo.order_id USING UTF8 ) = od.order_id

图片

查看执行计划,确实走了索引


# 解决方式


1、调整SQL语句

SELECT * FROM oc_order oo JOIN orders_detail od ON CONVERT ( oo.order_id USING UTF8 ) = od.order_id

2、调整字符集一致,建议


# 总结


可能不走索引的 3 种情况:


  1. 对索引字段做函数操作
  2. 隐式类型转换,字符串与数字比较,字符串会转换为数字
  3. 隐式字符集转换,utf8m4是utf8超集,utf8,与utf8mb4会比较,utf8会转换为utf8mb4

来源:my.oschina.net/floor/blog/4960148

往期回顾:

图片

2020年百日百更原创Java最全面试题库之往期回顾

【000期】Java最全面试题库思维导图

【020期】JavaSE系列面试题汇总(共18篇)

【028期】JavaWeb系列面试题汇总(共10篇)

【042期】JavaEE系列面试题汇总(共13篇)

【049期】数据库系列面试题汇总(共6篇)

【053期】中间件系列面试题汇总(共3篇)

【065期】数据结构与算法面试题汇总(共11篇)

【076期】分布式面试题汇总(共10篇)

【100期】综合面试题系列汇总(共23篇)

【151期】100-150期汇总(共50篇)

【201期】150-200期汇总(共50篇)

【202期】如何用 Redis 统计独立用户访问量?

【203期】Mybatis是如何运用设计模式的?

【204期】LRU的原理是什么?Redis是如何实现LRU的?

【205期】Feign的工作原理是什么?

【206期】数据库可以部署在容器中吗?为什么?

【207期】为什么SELECT * 效率低?

【208期】如何解决Redis主从集群切换数据丢失问题?

【209期】Java8中Stream对列表去重的方法有哪些?

【210期】Spring的Bean实例化过程是怎样的?

【211期】Tomcat 在 SpringBoot 中是如何启动的?

【212期】 Spring 注解式 AOP 的底层实现原理是什么?

【213期】如何保证缓存和数据库的一致性?

【214期】@Annotation注解的实现原理是什么?

【215期】说说你对 RabbitMQ 的理解以及使用它的场景

【216期】分布式 ID 解决方案有哪些?

【217期】你对MySQL中的索引了解多少?

【218期】SpringBoot中的@Import注解的原理是什么?

【219期】哈希表的原理是什么?

【220期】如何使用Redis实现电商系统的库存扣减?

【221期】一段Java代码是如何执行的?

【222期】为什么Integer用==比较时127相等而128不相等?

【223期】Java遍历Map集合有哪几种方式?各自效率如何?

【224期】try-catch-finally 和 return 的执行顺序是怎样的?

【225期】在不停止程序运行的情况下,如何实现对象(或者类)的动态替换?

【226期】1.3 万亿条数据查询,如何做到毫秒级响应?

【227期】Nacos的实现原理是什么?

【228期】说一下JDK/Dubbo/Spring 三种 SPI 机制?

【229期】ArrayList使用forEach遍历的时候删除元素会报错吗?

【230】熟悉红黑树吗?能不能手写一下?

【231期】JDK 序列化, 碰到serialVersionUID 不一致问题,怎么处理?

【232期】a==1 && a==2 && a==3 是 true 还是 false?

【233期】谈谈 Tomcat 架构及启动过程

【234期】说说Log4j2中RollingFile的文件滚动更新机制

【235期】在设计原则中,为什么反复强调组合要优于继承?

【236期】写时复制(Copy-On-Write)在Java中是如何被应用的?

【237期】说说Java的日志体系及各个组件之间的关系

【238期】线程池是如何重复利用空闲线程的?

【239期】说说Netty 实现长连接服务的难点和优化点

【240期】说说Redis的读写分离技术

【241期】说说你知道的MySQL中的各种锁

【242期】如何保证token的安全性?

【243期】谈谈你对缓存的使用和理解

【244期】写一个LFU缓存策略算法

【245】如何停止一个正在运行的线程?

【246期】如何解决集群环境下定时任务重复执行?






“一个专注于分享各类Java面试题的号主,长按二维码关注我吧 ”

祝大家都能拿到心仪的offer!

本文章转载自公众号:tikujie

首页 - Java 相关的更多文章: