根据时区快速查询大表

时间:2014-12-17 15:22:48

标签: mysql performance

我需要以最快的方式查询具有1,852,789,683179.3GB大小的表。我的条件是日本时间需要一整天(24小时)。

查询:

SELECT COUNT(*) CNT
  FROM info_table
 WHERE DATE(CONVERT_TZ(created_at, '+00:00', '+09:00')) = 20141216;

我已经让它运行了将近一个小时但现在还没有完成。有什么建议吗?

说明:

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  info_table  ALL NULL    NULL    NULL    NULL    1793315059  Using where

3 个答案:

答案 0 :(得分:3)

您的查询将在created_at列中为表中的每个翻转行评估该函数;这是一次全面扫描。

要使MySQL能够对索引执行有效的范围扫描操作,您需要引用谓词中的裸列,并且需要一个前导列为created_at的索引,并且查询需要是形式:

WHERE created_at >=  val1
  AND created_at <   val2

技巧将是开发val1和val2,这些表达式返回时间戳的上限和下限。


如果我们知道:

  DATE(CONVERT_TZ(created_at, '+00:00', '+09:00')) = 20141216

然后我们知道:

     CONVERT_TZ(created_at, '+00:00', '+09:00')) >= '2014-12-16'
 AND CONVERT_TZ(created_at, '+00:00', '+09:00')) <  '2014-12-17'

和(也许?)......

     created_at >= CONVERT_TZ('2014-12-16','+09:00','+00:00')
 AND created_at <  CONVERT_TZ('2014-12-17','+09:00','+00:00')

我不确定CONVERT_TZ函数的行为,无论转换是否等同于您案例中的所有值。同样,“技巧”将获得返回时间戳上限和下限的表达式。


<击>

<击>

在我们的环境中,我们将GMT用于数据库中的所有日期,日期时间和时间戳;我们使用GMT进行数据库连接。应用程序层执行适当的时区转换。当我需要像你一样做某事时,我倾向于写下这样的东西:

     created_at >= '2014-12-16' + INTERVAL   -9 HOUR
 AND created_at <  '2014-12-16' + INTERVAL 24-9 HOUR

<击>

答案 1 :(得分:1)

您应该创建语句,以便它利用索引,然后在需要经常运行时创建索引。如果表格太大,可能需要一些时间来创建索引。要使用和索引,您可以将语句重写为:

select count(*) cnt
from info_table
where created_at >=  '2014-12-16' and created_at<  '2014-12-17'

即使没有和索引,上面的内容可能会更快一些。

答案 2 :(得分:0)

问题是您在检查之前转换每个行值。将其改为另一方

SELECT COUNT(*) CNT
FROM info_table
WHERE created_at = YourConvertedTimeZoneDateValue