oracle “to_timestamp”是否应用于每一行?

vbkedwbf  于 7个月前  发布在  Oracle
关注(0)|答案(3)|浏览(60)

我需要查询一个大表(我使用Oracle)
和查询语句必须按时间戳数据类型搜索表
eg

SELECT * 
FROM rec 
WHERE timscolumn between to_timestamp('2023-07-02 00:00:00', 'YY-MM-DD HH24:MI:SS') AND to_timestamp('2023-08-25 23:59:59', 'YY-MM-DD HH24:MI:SS')

字符串
我的问题是,to_timestamp函数是否适用于每一行?
用于例如
我的rec表有100000000000行,我需要搜索日期之间2023-01-10 ~ 2023-12-10和时间戳类型列命名为timemumn。我有索引的时间列。
当我查询时,to_timestamp函数是否应用于每一行?我的意思是

数据库是否对每一行进行转换(字符串->时间戳)以进行比较?

在这种情况下,我认为这可能会导致严重的性能问题。(我在获取表时已经遇到了严重的性能问题,做了查询调优并解决了问题,但我仍然不确定是否可以使用to_timestamp
如果是重复的问题,我很抱歉。我在谷歌上搜索了一下,但还没有找到。如果你能链接任何好的参考资料或给予我任何解释,那将非常有帮助,谢谢。

cfh9epnr

cfh9epnr1#

数据库是否对每一行进行转换(字符串->时间戳)以进行比较?
不,你是把字符串'2023-07-02 00:00:00''2023-08-25 23:59:59'转换成TIMESTAMP,而不是把列timscolumn(我假设它已经是TIMESTAMP了)转换成TIMESTAMP,所以,不,文字的转换可以一次完成,并应用于所有行。
但是,您可以重写查询以使用TIMESTAMP文字,然后不需要转换任何内容:

SELECT * 
FROM   rec 
WHERE  timscolumn BETWEEN TIMESTAMP '2023-07-02 00:00:00'
                      AND TIMESTAMP '2023-08-25 23:59:59';

字符串
你也可以修改查询(假设你没有使用TIMESTAMP(0)),这样它就不会排除2023-08-25 23:59:59.0000000012023-08-25 23:59:59.999999999之间的时间戳:

SELECT * 
FROM   rec 
WHERE  timscolumn BETWEEN TIMESTAMP '2023-07-02 00:00:00.000000000'
                      AND TIMESTAMP '2023-08-25 23:59:59.999999999';


或者更简单地说:

SELECT * 
FROM   rec 
WHERE  timscolumn >= TIMESTAMP '2023-07-02 00:00:00'
AND    timscolumn <  TIMESTAMP '2023-08-26 00:00:00';

wlp8pajw

wlp8pajw2#

在你的代码中没有转换。
由于timscolumn的数据类型已经是timestamp,所以左边的一切都没问题。但是右边需要修改。如果年份是由4位数字表示的,请使用yyyy模型,而不仅仅是yy
如果timscolumn是例如varchar2,那么将它转换为时间戳,例如

WHERE to_timestamp(timscolumn, 'yyyy-mm-dd hh24:mi:ss') between ...

字符串
在这种情况下,timscolumn上的索引将不会被使用。不过,您可以创建一个基于函数的索引。
至于性能本身:如果表包含100.000.000.000行,返回结果将需要时间。

vdgimpew

vdgimpew3#

虽然其他答案正确地回答了你的字面问题,但你的问题的前提是错误的。即使Oracle确实愚蠢地为每行执行一次变量转换,这并不重要,因为**运行内置函数所需的时间与SQL性能无关。**将100亿个字符串转换为日期所需的CPU时间与读取或连接100亿行所需的时间相比只是一个舍入误差。
为了确保尽可能高效地读取和连接Oracle数据,您需要创建正确的物理数据结构(索引、分区、物化视图等),并且您需要给予Oracle优化程序足够的信息来预测基数,并选择最佳算法来阅读和连接数据。您可以通过尽可能简单和清楚地说明文字和表达式来提供更有用的信息。如果您担心性能,那么您应该担心执行计划中使用的算法和数据结构。
对于这种特定情况,您可以给予优化器更多的信息,如MT0所建议的那样,使用时间戳文字。使用TO_DATETO_TIMESTAMP的表达式并不像您想象的那样“文字”。不同的会话可能有不同的时区、月份名称或日历。您的TO_TIMESTAMP表达式并不能完全识别所有这些信息,因此,您的to_timestamp('2023-07-02 00:00:00', 'YY-MM-DD HH24:MI:SS')可能是另一个用户的to_timestamp('2023-07-02 00:00:00', 'YY-MM-DD HH24:MI:SS', 'nls_calendar=''thai buddha''')。虽然这种情况不太可能发生,但Oracle仍然必须对此进行计划,这可能会为所有会话提供一些rare performance implications
尽可能使用文字。

相关问题