零、背景
简朴网络一些信息后,发明这个慢查询题目隐蔽的很深,问了好多人包含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不能利用上索引是右值与左值的范例不一致致使的。 。
相干引荐:
MySQL中两表关联的衔接表怎样建立索引图文详解
MySQL分区字段列有必要再零丁建索引吗?
MySQL完成检察与建立以及删除索引的要领引见
以上就是mysql中索引与FROM_UNIXTIME的题目详解的细致内容,更多请关注ki4网别的相干文章!