2009-11-07 36 views
0

有时我在数据库中有一个日期时间或时间戳列,例如,我需要选择所有记录,其中包含今天更新的时间戳记。哪个是检查时间戳/日期时间是否属于指定日期的最佳方法

我通常不喜欢这样:

SELECT * FROM mytable WHERE CAST(TS AS DATE) = CURDATE(); 
SELECT * FROM mytable WHERE CAST(TS AS DATE) = '2009-11-01'; 

此外,它可以使用DATE()函数,而不是投:

SELECT * FROM mytable WHERE DATE(TS) = CURDATE(); 

的问题是,哪种方式更正确,更快?因为我不知道所有记录CAST是一个非常好的主意,也许有更好的办法...

回答

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

我会认为它更快地实际上不运行数据库列上的功能,而是做这样的事情

SELECT * FROM mytable WHERE TS >= UNIX_TIMESTAMP('2009-11-01 00:00:00') AND TS <= UNIX_TIMESTAMP('2009-11-01 23:59:59'); 

这样数据库只需要每次运行一次两个函数,并且可以使用列TS的索引。

+0

此查询无法按预期工作。请记住,TS的类型是TIMESTAMP。 UNIX_TIMESTAMP()返回INT。 – nightcoder 2009-11-07 13:39:22

1

运行一些测试。

我知道我们的数据仓库使用DATE()方法,他们每天处理数百万笔交易,所以它不会太坏。

2

假设你有ts索引,这将是最快的方法,因为它可以使用该索引:

SELECT * 
    FROM mytable 
WHERE ts >= CURDATE() 
    AND ts < (CURDATE() + INTERVAL 1 DAY) 
+0

谢谢,longneck,我现在最喜欢你的解决方案。 – nightcoder 2009-11-07 14:20:37

相关问题