mysql中索引与FROM_UNIXTIME的问题
零、背景
这周四收到很多告警,找DBA看了看,发现有个慢查询。
简单收集一些信息后,发现这个慢查询问题隐藏的很深,问了好多人包括DBA都不知道原因。
一、问题
有一个DB, 有一个字段, 定义如下.
MySQL [d_union_stat]> desc t_local_cache_log_meta; +----------------+--------------+------+-----+---------------------+ | Field | Type | Null | Key | Default | +----------------+--------------+------+-----+---------------------+ | c_id | int(11) | NO | PRI | NULL | | c_key | varchar(128) | NO | MUL | | | c_time | int(11) | NO | MUL | 0 | | c_mtime | varchar(45) | NO | MUL | 0000-00-00 00:00:00 | +----------------+--------------+------+-----+---------------------+ 17 rows in set (0.01 sec)
索引如下:
MySQL [d_union_stat]> show index from t_local_cache_log_meta \G *************************** 1. row *************************** Table: t_local_cache_log_meta Non_unique: 0 Key_name: PRIMARY Column_name: c_id Collation: A Cardinality: 6517096 Index_type: BTREE *************************** 2. row *************************** . . . *************************** 6. row *************************** Table: t_local_cache_log_meta Non_unique: 1 Key_name: index_mtime Column_name: c_mtime Collation: A Cardinality: 592463 Index_type: BTREE 6 rows in set (0.02 sec)
然后我写了一个SQL如下:
SELECT count(*) FROM d_union_stat.t_local_cache_log_meta where `c_mtime` < FROM_UNIXTIME(1494485402);
终于有一天DBA过来了, 扔给我一个流水,说这个SQL是慢SQL。
# Time: 170518 11:31:14 # Query_time: 12.312329 Lock_time: 0.000061 Rows_sent: 0 Rows_examined: 5809647 SET timestamp=1495078274; DELETE FROM `t_local_cache_log_meta` WHERE `c_mtime`< FROM_UNIXTIME(1494473461) limit 1000;
我顿时无语了,我的DB都是加了索引,SQL都是精心优化了的,怎么是慢SQL呢?
问为什么是慢SQL,DBA答不上来, 问了周围的同事也都答不上来。
我心里暗想遇到一个隐藏很深的知识点了。
令人怀疑的地方有两个:1.有6个索引。 2. 右值是 FROM_UNIXTIME 函数。
于是查询MYSQL官方文档,发现6个不是问题。
All storage engines support at least 16 indexes per table and a total index length of at least 256 bytes.
Most storage engines have higher limits.
于是怀疑问题是 FROM_UNIXTIME 函数了。
然后看看MYSQL的INDEX小节,找到一点蛛丝马迹。
1.To find the rows matching a WHERE clause quickly.
2. To eliminate rows from consideration.
If there is a choice between multiple indexes, MySQL normally uses the index that finds the smallest number of rows.
3.If the table has a multiple-column index, any leftmost prefix of the index can be used by the optimizer to look up rows.
4. MySQL can use indexes on columns more efficiently if they are declared as the same type and size.
Comparison of dissimilar columns (comparing a string column to a temporal or numeric column, for example) may prevent use of indexes if values cannot be compared directly without conversion.
看到第4条的时候,提到不同类型可能导致不走索引,难道 FROM_UNIXTIME 的返回值不能转化为字符串类型?
于是查询 FROM_UNIXTIME 函数的返回值。
MySQL FROM_UNIXTIME() returns a date /datetime from a version of unix_timestamp.
返回的是一个时间类型,那强制转化为字符串类型呢?
MySQL [d_union_stat]> explain SELECT -> * -> FROM -> t_local_cache_log_meta -> where -> `c_mtime` = CONCAT(FROM_UNIXTIME(1494485402)) \G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t_local_cache_log_meta type: ref possible_keys: index_mtime key: index_mtime key_len: 137 ref: const rows: 1 Extra: Using where 1 row in set (0.01 sec)
这次可以看到, 使用了索引,只扫描了一个数据。
二、结论
这次对 FROM_UNIXTIME 的返回值强制转化一下就可以利用上索引了。
所以这个SQL不能利用上索引是右值与左值的类型不一致导致的。 。
好了,不多说了, 这篇文章算是一个插曲,后面继续介绍算法吧。
- 微信小程序开发探索之路
- 前端周记 2017 年终总结
- asp.net mvc中的路径选择
- MVC中实现加载更多
- 在ASP.NET MVC 中获取当前URL、controller、action
- [转自Scott]ASP.NET MVC框架(第四部分): 处理表单编辑和提交场景
- MVC前台Post/Get异步获得数据时参数的取值问题
- IQueryable与foreach的困惑?
- ModalPopupExtender用法示例
- MVC中局部视图的使用
- MVC发布后项目存在于根目录中的子目录中时的css与js、图片路径问题
- ORM中的继承关系映射全解——单表继承体系、一实体一具体表、一实体一扩展表、接口映射
- View与Control间的数据交互
- C#中Dispose和Close的区别!
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- C++11标准常用特性---统一初始化
- QPainter的fillRect函数-QGradient-Preset渐变颜色预设值
- 深度学习|Tensorflow2.0进阶
- Mumble——简介及搭建
- 网站开启HSTS增强安全性
- 形式化分析工具(六):HLPSL Tutorial(Example 4,other)
- Typecho回复可见功能
- 微信小程序开发实战(13):图像组件(image)
- Typecho文章代码高亮功能
- “数据分析师”面试最怕被问到的SQL优化问题(下)
- 普通小程序的订阅消息不再限制时间
- Telnet 配置实验
- 网站加速那些事
- Python逻辑运算
- 获取小程序码并接受buffer流保存为图片的方法