【问题标题】:Oracle Composite Key Auto-Increment (Decrement!?)Oracle 复合键自动递增(递减!?)
【发布时间】:2011-10-18 11:19:20
【问题描述】:

我有一个相对较大的表(约 100 万条记录),它基本上是一个 XML 存储。可以有多个具有不同时间戳的 XML 文档(最新时间戳 = 最新版本的逻辑)。我们预计每月会有一批更新的数据,其中可能包含约 70% 的数据的新版本。

我们计划只在商店中保留最新的 2-3 个版本,所以我猜我们当前的 b-tree 索引(记录 ID、时间戳)不一定是最快的?昨晚,一个简单的“select * from table where timestamp >= yyyy-mm-dd order by record id, timestamp”查询花了 15 个小时才完成——相当高规格的工具包,我认为没有其他人在使用当时的数据库。

(回复:查询本身,理想情况下我只想选择时间戳 >= yyyy-mm-dd 的最新文档,但现在这不是问题)。

有什么办法可以创建一个自动递减列,如下:

Record ID   Timestamp    Version   XML
1           2011-10-18   1         <...>
1           2011-10-11   2         <...>
1           2011-10-04   3         <...>
2           2011-10-18   1         <...>
2           2011-10-11   2         <...>

etc etc - 即,当新版本出现时,最近的时间戳 = 版本 1,所有旧记录得到版本 = 版本 + 1。这样我的内务脚本可以是一个简单的“删除版本 > 3"(或我们决定保留的任何内容),我可以在记录 ID 上使用 b-tree 索引,在版本上使用二进制索引?

希望我没有完全在错误的树上吠叫 - 整个早上都在“创造性地谷歌搜索”,这就是我提出的理论......

【问题讨论】:

  • 每月批处理大约有 7000 万行。但是每天的批处理量大约为 250 万行。如果甚至有可能获得每日批次,那可能值得考虑。
  • 不可能——这是一个源驱动的决定。不过,它有它的好处 - 这意味着这些表几乎处于空闲状态,除了每月 1 天将数据插入其中,以及每月 1 天提取最新数据并将其传递到前端系统.所以插入/更新没有(实际的)时间限制,但选择(和后续处理)有一个约 72 小时的窗口,其中选择当前需要 15 小时......

标签: sql oracle indexing


【解决方案1】:

我不确定降低版本是否是一个好主意。唯一的方法是使用触发器查找匹配的记录 ID 并相应地更新它们。这对性能来说不是很好..

这就是我在我们的数据库环境(大小相似)中做类似事情的方式。希望它有用:

创建一个单独的存档表,用于保存您记录的所有版本。这将由插入主表时的触发器填充。触发器将insert 记录的当前版本放入您的存档,update 主表上的记录,增加版本号并更新时间戳和数据。

然后,当您只需要选择所有记录的最新版本时,您只需:

SELECT * FROM TABLE;

如果您需要查看数据在给定时间点的“快照”,您还需要表格中的valid_fromvalid_to 列来记录每个版本的记录是最新版本。您可以在写入存档表时使用触发器填充这些内容。

Valid_to对最新版本的一条记录可以设置为最大可用日期。当插入较新版本的记录时,您会将先前版本的 valid_to 更新为新记录的 valid_from 之前(为了避免被骗,这不一样)..

然后,当您想查看数据在给定时间的外观时,您可以使用 SQL 查询存档表,例如:

SELECT *
FROM ARCHIVE_TABLE a
WHERE <time you're interested in> BETWEEN a.valid_from AND a.valid_to

【讨论】:

    【解决方案2】:

    批处理工作绝对不同于典型的插入/更新方法(尤其是在涉及触发器或许多索引的情况下)。即使有不错的磁盘/硬件,你会发现传统的 DML 方法在这个卷上非常慢。对于每月批量更新 70mm 的 100mm + 表,我建议研究类似于以下的方法:

    1. 将新的批处理文件 (70mm) 加载到单独的表 (NEW_XML) 中,格式与现有表 (EXISTING_XML) 相同。使用 nologging 来避免撤销。

    2. 从 EXISTING_XML 追加(不记录)NEW_XML 中不存在的记录(30 毫米记录,基于您已经使用的任何键)。

    3. 将 EXISTING_XML 重命名为 HISTORY_XML,将 NEW_XML 重命名为 EXISTING_XML。在这里,您可能需要一些停机时间,也许是周末的下班时间。这实际上不会花费任何时间,但是您需要时间进行下一步(并且由于对象无效)。如果您已有上个月的 HISTORY_XML,请先截断并删除它(保留 1 个月的旧数据)。

    4. 在 EXISTING_XML(现在也包含新数据)上构建索引、统计信息、约束等。重新编译任何无效的对象,使用日志记录等。

    简而言之,您将拥有一个表 (EXISTING_XML),它不仅包含新数据,而且构建速度相对较快(比 DML/触发器方法快很多倍)。此外,如果需要,您可以尝试在步骤 2 中使用并行。

    希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 2016-04-04
      • 2015-06-08
      • 2017-10-14
      • 1970-01-01
      • 2014-03-18
      • 2011-01-25
      • 2015-09-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多