MySql转换问题:从UNIX_TIMESTAMP到INT(11)

时间:2010-01-25 23:08:45

标签: mysql types

在包含1500000行的MySql表上运行以下select将花费大约5分30秒。

SELECT * FROM my_table WHERE timestamp BETWEEN UNIX_TIMESTAMP('2008-04-23 01:37:02') AND  UNIX_TIMESTAMP('2008-04-23 01:37:03')

[Executed: 25/01/10 5:32:47 EST PM ] [Execution: 231094/ms] 

在上述查询中转换和替换 UNIX_TIMESTAMP 函数返回的值将大大缩短持续时间:

SELECT UNIX_TIMESTAMP('2008-04-23 01:37:02'),  UNIX_TIMESTAMP('2008-04-23 01:37:03')

UNIX_TIMESTAMP('2008-04-23 01:37:02')     UNIX_TIMESTAMP('2008-04-23 01:37:03')    
----------------------------------------  ---------------------------------------- 
1208911022                                1208911023                               


SELECT * FROM my_table WHERE timestamp BETWEEN 1208911022 AND 1208911023

[Executed: 25/01/10 5:58:27 EST PM ] [Execution: 11875/ms] 

时间戳列的类型为 INT(11)

我们不在这里讨论索引 - 我不是数据库的所有者,但我会要求该列的索引。

我想问你为什么两个查询之间存在巨大的持续时间差异?

似乎 timestamp 列中的每个 INT(11)值都转换为 UNIX_TIMESTAMP 返回的值的类型!


更新1


MySql版本:

SELECT VERSION()

5.1.23-rc-log

解释结果:

EXPLAIN SELECT * FROM my_table WHERE timestamp BETWEEN UNIX_TIMESTAMP('2008-04-23 01:37:02') AND  UNIX_TIMESTAMP('2008-04-23 01:37:03')

 id     select_type     table          type     possible_keys     key     key_len     ref     rows      Extra       
 -----  --------------  -------------  -------  ----------------  ------  ----------  ------  --------  ----------- 
 1      SIMPLE          my_table       ALL      (null)            (null)  (null)      (null)  15046061  Using where 

EXPLAIN SELECT * FROM my_table WHERE timestamp BETWEEN 1208911022 AND 1208911023

 id     select_type     table          type     possible_keys     key     key_len     ref     rows      Extra       
 -----  --------------  -------------  -------  ----------------  ------  ----------  ------  --------  ----------- 
 1      SIMPLE          my_table       ALL      (null)            (null)  (null)      (null)  15046061  Using where 



更新2


SELECT * FROM my_table WHERE timestamp >= UNIX_TIMESTAMP('2008-04-23 01:37:02') AND timestamp <= UNIX_TIMESTAMP('2008-04-23 01:37:03')

 [Executed: 26/01/10 10:29:52 EST AM ] [Execution: 264172/ms] 

EXPLAIN SELECT * FROM my_table WHERE timestamp >= UNIX_TIMESTAMP('2008-04-23 01:37:02') AND timestamp <= UNIX_TIMESTAMP('2008-04-23 01:37:03')

 id     select_type     table          type     possible_keys     key     key_len     ref     rows      Extra       
 -----  --------------  -------------  -------  ----------------  ------  ----------  ------  --------  ----------- 
 1      SIMPLE          my_table       ALL      (null)            (null)  (null)      (null)  15046061  Using where 

似乎&gt; =和&lt; =没有任何区别 - 运行时间超过5分钟!

3 个答案:

答案 0 :(得分:2)

我使用MySQL的BENCHMARK()函数运行了这两个查询:

mysql> SELECT BENCHMARK(15000000, 1208911022 BETWEEN 
UNIX_TIMESTAMP('2008-04-23 01:37:02') AND  UNIX_TIMESTAMP('2008-04-23 01:37:03'));
1 row in set (33.28 sec)

mysql> SELECT BENCHMARK(15000000, 1208911022 BETWEEN 1208911022 AND 1208911023);
1 row in set (0.52 sec)

似乎MySQL不够聪明,不能分解UNIX_TIMESTAMP()表达式,即使它们应该是常量。 MySQL在表达式的每次迭代期间评估函数。因此,在此测试中使用此函数的速度大约慢64倍。

我在MacBook 2.4GHz Intel Core 2 Duo上运行MySQL 5.1.41。

我建议您在准备查询之前将时间戳转换为整数值。

答案 1 :(得分:0)

我不是mySQL大师,但看起来mySQL并没有优化语句的BETWEEN部分,而是为每一行重新执行它,或者不使用列的索引集。 (我觉得很奇怪,看到UNIX_TIMESTAMP操作的结果是固定的,但我没有其他解释。)

您可以尝试使用>=<=代替BETWEEN,看看是否会改变时间吗?

答案 2 :(得分:0)

因为它似乎不是索引或“介于”问题之间,所以可能正在评估UNIX_TIMESTAMP函数以与每行进行比较。也就是说,它没有考虑结果是一个常数。如果是这种情况,您可以计算运行UNIX_TIMESTAMP函数150万次的开销:)