| 您的当前位置:首页 --> MYSQL教程 --> mysql中索引与FROM_UNIXTIME的问题 |
| MYSQL教程 mysql中索引与FROM_UNIXTIME的问题 |
| 浏览次数:1438 关键词 ( ) |
| 查看使用该CPU的产品 查看CPU天梯 |
| CPU型号:mysql中索引与FROM_UNIXTIME的问题 |
| 主频:Ghz |
| 睿频:Ghz |
| 核心数:个 |
| 不支持超核心 |
| 制作工艺: |
| 插槽类型: |
| 功耗:0W |
| L3缓存:0MB |
| 支持最大内存: 0GB |
| CPU详细参数 |
|
零、背景 这周四收到很多告警,找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. 于是怀疑问题是 FROM_UNIXTIME 函数了。 然后看看MYSQL的INDEX小节,找到一点蛛丝马迹。 1.To find the rows matching a WHERE clause quickly. 看到第4条的时候,提到不同类型可能导致不走索引,难道 FROM_UNIXTIME 的返回值不能转化为字符串类型? 于是查询 FROM_UNIXTIME 函数的返回值。
返回的是一个时间类型,那强制转化为字符串类型呢?
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不能利用上索引是右值与左值的类型不一致导致的。 。 好了,不多说了, 这篇文章算是一个插曲,后面继续介绍算法吧。 |
| 下一个产品 SQL计算timestamp的差值的方法 上一个产品 mysql中mydumper 和 mysqldump 对比使用 |