使用“WHERE UNIX_TIMESTAMP(date)”执行SQL查询的性能

时间:2012-07-19 16:47:54

标签: mysql sql performance

我正在运行一个MySQL服务器(5.5),它有一个大表(大约有10M记录)。此表是某种日志,其中包含2列主键:

id <- integer,
date <- datetime

连接到此数据库的应用程序正在发送一个类似以下内容的查询:

SELECT * FROM bigtable  
INNER JOIN other_table
ON ....
WHERE UNIX_TIMESTAMP(date) BETWEEN #somevalue# AND #somevalue2#;

我发现这个查询花了很多时间来执行。我知道有些函数可以阻止MySQL使用索引并使其执行全表扫描。

问题: 如图所示,通过在主键的列上使用UNIX_TIMESTAMP功能而不是 “... WHERE date BETWEEN'2012:01:01 00:00:00'AND'2012: 02:01 00:00:00'“

查询:

SELECT r.f_registro, r.latitud, r.longitud, r.velocidad, r.status, r.odometro, r.heading, r.sensor, a.nombre FROM registros r INNER JOIN activos a ON a.id_tracker = r.id_tracker WHERE a.id_activo = 2366 AND r.satelites > '3' AND UNIX_TIMESTAMP(r.f_registro) BETWEEN 1342159200 AND 1342760400 ORDER BY r.f_registro

执行需要几秒甚至几分钟! 运行说明返回:

id,select_type,table,type,possible_keys,key,key_len,ref,rows,Extra
1,SIMPLE,a,const,PRIMARY,PRIMARY,4,const,1,"Using filesort"
1,SIMPLE,r,range,"id_tracker,satelites",satelites,4,NULL,1,"Using index condition; Using where"

2 个答案:

答案 0 :(得分:6)

使用日期列上的函数可以防止MySQL使用列上的索引。

相反,将范围计算为两个日期常量并使用BETWEEN。

另请注意,您没有表明日期列上有索引。索引保留最多前缀,因此以id开头的复合索引不能用于仅请求日期的查询。

查询的ON部分(您已排除)可能在查询性能中同样重要,您应该评估是否也能使用索引。

答案 1 :(得分:5)

如果您的日期范围必须是UNIX时间,则可以更改:

UNIX_TIMESTAMP(r.f_registro) BETWEEN 1342159200 AND 1342760400

为:

r.f_registro BETWEEN FROM_UNIXTIME(1342159200) AND FROM_UNIXTIME(1342760400)

这将大大加快查询速度。在我的情况下(有3.8亿行和索引日期的列),这表示从小时到毫秒的变化。