在包含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 返回的值的类型!
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
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分钟!
答案 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万次的开销:)