有时我在数据库中有一个日期时间或时间戳列,例如,我需要选择今天更新时间戳的所有记录。
我通常这样做:
SELECT * FROM mytable WHERE CAST(TS AS DATE) = CURDATE();
SELECT * FROM mytable WHERE CAST(TS AS DATE) = '2009-11-01';
此外,可以使用DATE()函数代替cast:
SELECT * FROM mytable WHERE DATE(TS) = CURDATE();
问题是哪种方式更正确,更快?因为我不确定所有记录的CAST是一个非常好的主意,也许有更好的方法......
答案 0 :(得分:4)
好的,我做了一些测试,结果如下。第一个值是TS列上的索引,第二个值是TS列上没有索引。
SELECT * FROM parts WHERE CAST(TS AS DATE) = DATE('2009-10-01');
2.1秒,2.1秒
SELECT * FROM parts WHERE DATE(TS) = DATE('2009-10-01');
2.1秒,2.1秒
SELECT * FROM parts WHERE TS >= DATE('2009-10-01') AND TS < (DATE('2009-10-01') + INTERVAL 1 DAY);
0.1秒,2.15秒
SELECT * FROM parts WHERE TS >= '2009-10-01' AND TS < '2009-10-01 23:59:59';
0.1秒,2.15秒
因此,正如您所看到的,如果我们在TS列上没有索引,则没有区别。但是当我们有索引时,存在很大的差异。当我们在索引列上使用CAST()或DATE()时,索引不能再使用了,所以我们得到了不好的结果。
至于我,我会选择这个解决方案:
SELECT * FROM parts WHERE TS >= DATE('2009-10-01') AND TS < (DATE('2009-10-01') + INTERVAL 1 DAY);
我认为这是最优雅的。
PS。我仍然在寻找更好的解决方案,所以如果你有一个 - 请分享。
答案 1 :(得分:2)
假设你有ts
的索引,这将是最快的方式,因为它可以使用该索引:
SELECT *
FROM mytable
WHERE ts >= CURDATE()
AND ts < (CURDATE() + INTERVAL 1 DAY)
答案 2 :(得分:1)
我认为实际上没有在数据库列上运行函数更快,而是做类似这样的事情
SELECT * FROM mytable WHERE TS >= UNIX_TIMESTAMP('2009-11-01 00:00:00') AND TS <= UNIX_TIMESTAMP('2009-11-01 23:59:59');
这样,DB只需要每次运行两个函数,并且可以使用列TS的索引。
答案 3 :(得分:1)
进行一些测试。
我知道我们的数据仓库使用DATE()方法,他们每天处理数百万个交易,所以它不会太糟糕。