我需要以最快的方式查询具有1,852,789,683
行179.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
答案 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