开发者社区> db匠> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

MySQL · 最佳实践 · 一个“异常”的索引选择

简介: 背景 在处理一个用户性能问题的时候, 发现有一个全表扫描语句, 上下文如下: 这是很奇怪的, Tips: MySQL在执行条件判断时,若参数类型与字段类型不匹配, 则会作类型转换, 符合转换规则的, 转换完成后可以利用索引 而当参数为字符串,字段类型为整型时, 这个转换是成立的, 比如这个case.
+关注继续查看

背景

在处理一个用户性能问题的时候, 发现有一个全表扫描语句, 上下文如下: 这是很奇怪的,

Tips: MySQL在执行条件判断时,若参数类型与字段类型不匹配, 则会作类型转换, 符合转换规则的, 转换完成后可以利用索引

而当参数为字符串,字段类型为整型时, 这个转换是成立的, 比如这个case.

因此我们有必要查一下是什么原因.

分析

在优化器执行流程中, 要选择索引, 需要先判断where的部分的条件操作能否使用索引.经典的有,

Tips: 在字段上作函数操作,是无法使用索引的. 比如 where c+1 = 10

因此怀疑是在判断过程出了什么岔子.

调用栈 mysql_select->mysql_execute_select->JOIN::optimize->get_quick_record_count->SQL_SELECT::test_quick_select->get_mm_tree->get_full_func_mm_tree->get_func_mm_tree

一路下来都是预期内调用,直到 get_func_mm_tree返回了 NULL, 表示这个语句无法使用索引.

然后我们发现了这样一段代码,

简单说,就是在IN的入口有一个判断, 如果in中的字段类型不兼容, 则认为不可使用索引. 而这个arg_types_compatible 的赋值逻辑是: if (type_cnt == 1) arg_types_compatible = TRUE; 也就是说,当IN列表中出现超过一个字段类型时, 就认为类型不兼容.

这个本来是一个优化操作, 提前判断避免额外的后续判断.

对照实验

至此,我们就清楚, 问题来自于IN和列表中的类型问题. 以下几个对照试验可以作为验证:

where id in ('1', '1') 可以使用索引

where id = '1' or id = 1 可以使用索引

是不是bug?

如果把他当作bug处理,只需要在get_func_mm_tree函数中去掉上述最后一个图中的判断逻辑即可, 有兴趣的读者可以自己注释后验证.

前面的用户场景使用的是5.6,作为验证,我们测试了5.7版本,结果发现,5.7中可以相同的语句序列使用此索引!

翻了代码发现果然是去掉了这个判断.

但有趣的是, 官方并不是为了解决这个问题而作的修改, 实际上是在支持(a,b) in (X, Y)这样的语法时,由于这个语句就不能要求XY必须相同类型,因此去掉了这个判断, “阴差阳错”把这个问题改过来了.

翻了下commit log, 发现在5.7.3修复的, 因5.7.3之后,文章开头的这个例子的优化器结果就变了.

更多

所以我们看到, 实际上即使是小版本, 也是可能改变程序行为的.

而版本更新,尤其是要使用官方最新版本的特性, 有时候是必须作程序升级的.

而即使是小版本号的不同, 也可能对业务造成影响.

上述这个需求和现状,其实是有矛盾的, 运维的同学们可以考虑下, 如何处理这种潜在风险呢?

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
MySQL · 引擎特性 · 安全及权限改进相关
MySQL8.0里引入了不少关于权限的改动,从这些改动可以看出来,权限管理更加的规范和遍历了,这和我们之前为rds mysql增加了大量权限管理很类似,想来Oracle也是通过这些改动为其云业务服务的吧。 本文主要简述下部分相关的权限改动,不会涉及代码实现部分。
0 0
MySQL · 特性分析 · MyRocks简介
RocksDB是facebook基于LevelDB实现的,目前为facebook内部大量业务提供服务。经过facebook大量工作,将RocksDB作为MySQL的一个存储引擎移植到MySQL,称之为MyRocks。 经过两年的发展,MyRocks已经比较成熟(RC阶段),现已进入了facebook MySQL的主分支了。MyRocks是开源的,参见git 。 下面对MyRocks做一个简单介绍,
2027 0
MySQL · 最佳实战 · 审计日志实用案例分析
审计日志是RDS安全策略中非常重要的一环,它采集了数据库中所有的访问请求,包括常见的insert,update,delete,select,alter,drop,create语句, 还有一些比如set,commit,rollback命令语句。有了这些日志后可以帮助我们进行问题回溯,分析问题。下面这则案例讲述如何使用审计日志来分析只读实例延迟问题,如果没有审计日志我们很难想象该问题该如何解决。
1555 0
MySQL · 捉虫动态 · MySQL 外键异常分析
外键约束异常现象 如下测例中,没有违反引用约束的插入失败。 create database `a-b`; use `a-b`; SET FOREIGN_KEY_CHECKS=0; create table t1(c1 int primary key, c2 int) engine=inno
1247 0
+关注
db匠
rds内核团队秘密研发的全自动卖萌机. 追加特效: 发数据库内核月报. 月报传送: http://mysql.taobao.org/monthly/
文章
问答
来源圈子
更多
让用户数据永远在线,让数据无缝的自由流动
+ 订阅
文章排行榜
最热
最新
相关电子书
更多
2019大数据技术公开课第五季—MySQL/RDS数据如何同步到MaxCompute
立即下载
阿里云 AnalyticDB MySQL版性能白皮书
立即下载
PostgresChina2018_张启程_为什么我们抛弃MongoDB和MySQL,选择PgSQL
立即下载