【问题标题】:MySql conversion problem : from UNIX_TIMESTAMP to INT(11)MySql 转换问题:从 UNIX_TIMESTAMP 到 INT(11)
【发布时间】:2010-01-25 23:08:45
【问题描述】:

在包含 1500000 行的 MySql 表上运行以下选择大约需要 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 返回的值的类型! p>

更新 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 

似乎 >= 和

【问题讨论】:

  • 请发布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')EXPLAIN SELECT * FROM my_table WHERE timestamp BETWEEN 1208911022 AND 1208911023的结果。这将告诉您正在使用哪些索引。 MySQL is not 在第一个查询中使用索引而 is 在第二个查询中使用索引很可能。
  • 添加了 EXPLAIN 计划和 MySQL 版本。
  • 感谢您发布EXPLAIN 声明的结果。我现在可以看到没有使用任何索引。能否请您发布SHOW CREATE TABLE my_table; 的结果,以便我们查看表上有哪些索引?

标签: mysql types


【解决方案1】:

我使用 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。

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

【讨论】:

    【解决方案2】:

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

    您可以尝试使用 &gt;=&lt;= 代替 BETWEEN 看看这是否会改变时间?

    【讨论】:

    • 明天我会试试你的建议。但是你如何解释当我输入固定值时它工作得更快?
    • @Adrian S.:请运行我在对您的问题的评论中发布的EXPLAIN 声明。这些输出将讲述完整的故事。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多