准备好的语句:比较时间戳和分钟的粒度
Prepared statement: Compare timestamp with granularity of minutes
我用 SQL 语句创建了一个 PreparedStatement
,如下所示:
SELECT *
FROM MY_TABLE
WHERE MY_DATE = ?
我将 MY_DATE
值设置为
preparedStatement.setTimestamp(1, myDate);
这样数据库会检查整个时间戳是否相等。
现在我想将“刚刚”的粒度减少到几分钟。我怎样才能做到这一点?
如果你使用TRUNC()函数,那么你可以忽略值的粒度,低于某个级别。
所以,在你的情况下:
SELECT *
FROM MY_TABLE
WHERE TRUNC(MY_DATE, 'MI') = TRUNC(?, 'MI')
可以使用其他粒度:有关详细信息,请参阅 Oracle's Documentation(默认为在相关日期截断为 00:00:00)。
当然,如果您存储的时间戳已被截断为分钟,那么您可以省略左侧的 TRUNC 调用,并利用索引(如果该列上有索引)。
使用TRUNC 会抑制日期列 上的任何常规索引。提高性能的一种方法是创建一个 基于函数的索引 。
但是,更好的方法是使用显式范围条件。
例如,
SELECT *
FROM MY_TABLE
WHERE
MY_DATE >= TO_DATE('24-MAR-2015','DD-MON-YYYY')
AND MY_DATE < TO_DATE('24-MAR-2015','DD-MON-YYYY')+1;
或者,
使用BETWEEN(无论如何都会被优化器重写为上述范围条件):
SELECT *
FROM MY_TABLE
WHERE
MY_DATE BETWEEN TO_DATE('24-MAR-2015','DD-MON-YYYY')
AND TO_DATE('24-MAR-2015','DD-MON-YYYY') + (1-1/24/60/60);
更多信息
有了范围条件,优化器实际上按以下方式重写了查询:
access("MY_DATE">=TO_DATE(' 2015-03-24 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
"MY_DATE"<TO_DATE(' 2015-03-24 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))
并且将有一个 INDEX RANGE SCAN
操作而不是 TABLE ACCESS FULL
。如果使用 TRUNC,没有基于函数的索引,这就是优化器应用过滤谓词的方式:
filter(TRUNC(INTERNAL_FUNCTION("MY_DATE"))=TO_DATE(' 2015-03-24 00:00:00',
'syyyy-mm-dd hh24:mi:ss'))
的好文章
我用 SQL 语句创建了一个 PreparedStatement
,如下所示:
SELECT *
FROM MY_TABLE
WHERE MY_DATE = ?
我将 MY_DATE
值设置为
preparedStatement.setTimestamp(1, myDate);
这样数据库会检查整个时间戳是否相等。
现在我想将“刚刚”的粒度减少到几分钟。我怎样才能做到这一点?
如果你使用TRUNC()函数,那么你可以忽略值的粒度,低于某个级别。
所以,在你的情况下:
SELECT *
FROM MY_TABLE
WHERE TRUNC(MY_DATE, 'MI') = TRUNC(?, 'MI')
可以使用其他粒度:有关详细信息,请参阅 Oracle's Documentation(默认为在相关日期截断为 00:00:00)。
当然,如果您存储的时间戳已被截断为分钟,那么您可以省略左侧的 TRUNC 调用,并利用索引(如果该列上有索引)。
使用TRUNC 会抑制日期列 上的任何常规索引。提高性能的一种方法是创建一个 基于函数的索引 。
但是,更好的方法是使用显式范围条件。
例如,
SELECT *
FROM MY_TABLE
WHERE
MY_DATE >= TO_DATE('24-MAR-2015','DD-MON-YYYY')
AND MY_DATE < TO_DATE('24-MAR-2015','DD-MON-YYYY')+1;
或者,
使用BETWEEN(无论如何都会被优化器重写为上述范围条件):
SELECT *
FROM MY_TABLE
WHERE
MY_DATE BETWEEN TO_DATE('24-MAR-2015','DD-MON-YYYY')
AND TO_DATE('24-MAR-2015','DD-MON-YYYY') + (1-1/24/60/60);
更多信息
有了范围条件,优化器实际上按以下方式重写了查询:
access("MY_DATE">=TO_DATE(' 2015-03-24 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
"MY_DATE"<TO_DATE(' 2015-03-24 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))
并且将有一个 INDEX RANGE SCAN
操作而不是 TABLE ACCESS FULL
。如果使用 TRUNC,没有基于函数的索引,这就是优化器应用过滤谓词的方式:
filter(TRUNC(INTERNAL_FUNCTION("MY_DATE"))=TO_DATE(' 2015-03-24 00:00:00',
'syyyy-mm-dd hh24:mi:ss'))
的好文章