【问题标题】:Why does Oracle implicitly add SYS_EXTRACT_UTC to index?为什么 Oracle 隐式添加 SYS_EXTRACT_UTC 到索引?
【发布时间】:2021-05-16 13:55:30
【问题描述】:

我有一个表,其中包含一个 TIMESTAMP(6) WITH TIME ZONE 列,以及一个 INTERVAL DAY(4) TO SECOND(0) 列。为了清楚起见,我们假设以下 DDL:

CREATE TABLE TEST_TABLE
(
 time_col TIMESTAMP(6) WITH TIME ZONE,
 interval_col INTERVAL DAY(4) TO SECOND(0)
);

此表包含使用这两列的索引:

CREATE INDEX IDX_DELAY ON TEST_TABLE(time_col+interval_col);

运行此 DDL 时,Oracle 创建索引但隐式添加 SYS_EXTRACT_UTC 函数:

CREATE INDEX IDX_DELAY ON TEST_TABLE(SYS_EXTRACT_UTC(time_col+interval_col));

过去在其他数据库上运行过相同的 DDL,并且 SYS_EXTRACT_UTC 函数不存在。我不知道数据库是否从旧版 Oracle 迁移而来,但目前它们都在 12c (12.1.0.2.0) 上运行。我在其中一个上删除了索引并重新创建了它,这导致 Oracle 添加了 SYS_EXTRACT_UTC 函数。

为什么会这样?以前的 Oracle DB 版本中的行为是否发生了变化?此外,在索引中包含此功能(或缺少此功能)可能会产生什么影响?

提前致谢!

【问题讨论】:

  • 您确定吗,即旧数据库上的数据类型是否相同?我使用TIMESTAMP WITH TIME ZONE 很长时间,索引始终是SYS_EXTRACT_UTC。也许它只是一个隐藏的列,查看ALL_TAB_COLS(不是ALL_TAB_COLUMNS
  • @WernfriedDomscheit 这些列的定义完全相同。我检查了ALL_TAB_COLS,并且在“旧”数据库中,TIMESTAMP(9) WITH TIME ZONE 中隐藏列的DATA_TYPEDATA_DEFAULT 值为"TIME_COL"+"INTERVAL_COL"。但是,在“新”数据库中,DATA_TYPETIMESTAMP(9)DATA_DEFAULTSYS_EXTRACT_UTC("TIME_COL"+"INTERVAL_COL")

标签: sql oracle indexing oracle12c utc


【解决方案1】:

一种或另一种方式,要创建一个索引,您必须能够相互比较值(决定它们是否相等,或者决定哪个更大哪个更小)。为了将时间戳与时区进行比较,您必须将它们转换为单个时区; UTC 似乎是一个自然的选择。

如果没有先将它们转换为标准时区,我无法判断旧版本中的 Oracle 是否真的在索引中存储了带有时区的时间戳;也许确实如此,这就是为什么您在旧版本中看不到 SYS_EXTRACT_UTC 的原因。如果是这样,那么有人有 的想法来使用此函数,并将规范化 时间戳存储在索引中,这是一件好事。这让一切变得更简单、更高效。

当然,甲骨文也有可能一直在做这件事,他们最近才决定向我们展示它到底在做什么。 p>

无论如何,我看不出你有什么理由担心这个。有什么顾虑?

编辑 - 通过 Google 搜索,我找到了 Jonathan Lewis 的这篇文章;他说他从 2013 年开始撰写有关它的文章,也就是 Oracle 12 发布的时候。也许这是一个巧合,或者该版本中确实发生了一些变化(创建/存储索引的实际方式,或者 Oracle 选择向我们展示)。 p>

https://jonathanlewis.wordpress.com/2019/05/29/timestamp-oddity/

【讨论】:

  • 您好@mathguy,感谢您的详细回答。我同意,使用该功能似乎是个好主意。我在这里关心的是了解为什么这些数据库之间的结构不同,以及我们是否应该重建不使用SYS_EXTRACT_UTC 的“旧”索引。我的搜索也让我找到了那篇文章和其他提到 Oracle 12c 的文章,但我没有找到任何可以支持该理论的实际文档。此外,Oracle 似乎以不同的方式存储它们,正如您在我在原始答案中对@WernfriedDomscheit 所做的评论中所看到的那样。
  • 一开始我并没有完全理解你的解释,但现在我明白了。尽管 Oracle 过去使用时区存储时间戳,但在执行比较时,它仍然将所有内容转换为 UTC,例如在 ORDER BYWHERE 子句中。最有可能的是,Oracle 12 中的变化是现在所有内容都在创建索引时进行了转换,并且已经存储为 UTC。我进行了一些快速测试,没有发现“旧”索引有任何问题,所以我同意没有必要担心。
猜你喜欢
  • 2016-09-16
  • 1970-01-01
  • 2018-01-27
  • 1970-01-01
  • 2016-01-13
  • 1970-01-01
  • 2012-01-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多