1

我有一个包含时区类型列的表。此列已编入索引。

此查询使用索引:

select t.*
from <table> t
where t.load_date = to_timestamp('1 may 2013', 'dd mon yyyy') 
order by t.load_date;  

这个(加上时区转换)没有,并且暗示它强制使用索引也不起作用:

select t.*
from <table> t
where t.load_date = to_timestamp('1 may 2013', 'dd mon yyyy') at time zone 'US/Pacific'
order by t.load_date;  

有人可以解释为什么后一个查询需要 FTS 吗?

谢谢。

4

1 回答 1

0

假设load_date是 atimestamp而不是 a timestamp with time zone,解释计划将显示如下内容:

filter=SYS_EXTRACT_UTC(INTERNAL_FUNCTION("LOAD_DATE"))=
    SYS_EXTRACT_UTC(TIMESTAMP('2013-05-01 00:00:00000000000' AT TIME ZONE 'US/Pacific'))

如果该列是timestamp with time zone,它不会INTERNAL_FUNCTION()在左侧调用,允许它用于访问(即索引查找)而不仅仅是作为过滤器:

access(SYS_EXTRACT_UTC("LOAD_DATE")=
    SYS_EXTRACT_UTC(TIMESTAMP('2013-05-01 00:00:00000000000' AT TIME ZONE 'US/Pacific'))

您的列必须在内部从一种类型转换为另一种类型,并且必须对每一行进行转换,然后才能将转换后的值与您的过滤器值进行比较。在这种情况下,Oracle 不使用索引 - 如果必须将显式或隐式函数应用于索引列,它通常不会使用。

(可以说它可以使用全索引扫描来获取要转换的值,但由于它不知道有多少将匹配过滤器,它最终可能不得不从实际表中检索这么多行,它仍然会结束更贵。我不知道它是如何在内部做出这些决定的;根据我的经验,它只是忽略了索引。有趣的是,这个SYS_EXTRACT_UTC调用似乎是一个例外)。

于 2013-07-10T08:46:56.303 回答