【问题标题】:Oracle doing full table scan when converting timezoneOracle在转换时区时进行全表扫描
【发布时间】:2013-07-10 08:09:22
【问题描述】:

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

此查询使用索引:

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 吗?

谢谢。

【问题讨论】:

  • load_date 是什么数据类型?

标签: sql oracle timezone full-text-search


【解决方案1】:

假设load_datetimestamp,而不是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 调用似乎是一个例外)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-04
    • 2015-12-04
    • 1970-01-01
    • 2013-01-07
    相关资源
    最近更新 更多