8

在 Oracle 数据库中有一个伪列,称为ora_rowscn. 如果检索到它,它会显示该行最近更改的 SCN(如文档中所述)。

还有一个选项可以rowdependenciesCREATE TABLE每一行而不是整个数据块(这是默认设置)打开 SCN 的存储。

因此,我使用此列的值来指示哪些行已更新并且需要上传到另一个数据库。

让我们考虑这个例子:

  1. T1架构中有一个表,S1其中包含数百万条记录(常规查询无法承受对表的全面扫描)。

    CREATE TABLE T1 {
      A INTEGER PRIMARY KEY,
      B VARCHAR2(100),
      C DATE
    }
    /
    
  2. 有模式S2, S3, S4, S5..,每个模式都有 table T2

    CREATE TABLE T2 {
      A INTEGER
    }
    /
    
  3. 中只有一行T2,但T2.A不同模式中的值可能不同。

所以,我需要在每个模式中检索(S2, S3, S4...)所有S1.T1ora_rowscn大于的行S*.T2.A(然后我使用这个数据块)。在获取这些行之后,我S*.T2.A用当前系统 SCN ( dbms_flashback.get_system_change_number) 重写了 的值。

任何模式的以下查询都在这里:

查询一:

SELECT * FROM S1.T1 WHERE ora_rowscn > (SELECT A FROM T2);

查询 2(它在我完成上一个查询返回的数据集的工作时执行):

UPDATE T2 SET A = dbms_flashback.get_system_change_number;

问题是查询 1 的性能不可接受(对表进行全扫描)并且无法S1.T1为该列建立索引。ora_rowscn

问题:有什么方法可以提高查询 1 的性能?

4

2 回答 2

7

你不能索引ora_rowscn。因此,查询 1 的最佳计划是FULL TABLE SCAN.

由于这是不可接受的,您将不得不使用另一个标记,例如last_updated date列。此列是可索引的,但您必须对其进行更新。您可以使用小型轻量级触发器自动执行此更新。

针对索引列的查询 1 的性能将取决于检索的行数。

于 2013-05-15T12:57:14.630 回答
0

您只关心自上次运行上传以来插入或更新了哪些行。

为什么不在表中添加一个标志,将每一行标记为“脏” - 即插入前触发器会将其设置为“X”,而更新前触发器会将其设置为“X”。

然后,编写上传过程以查询表中标志为 NOT NULL 的任何行,然后在成功时将标志设置为 NULL。请注意,这意味着在上传过程中插入/更新的新行仍将被正确标记,并将在下次上传运行时被拾取。

如果插入/更新的行数与表中的总行数相比是一个非常小的比例,那么在标志上的索引将很有用,因为 NULL 标志不会存储在索引中(即索引通常会很小。

编辑:

对于需要更新多个模式的情况,一个等效的解决方案是使用一个单独的表来保存已更改行的 ID。该表应该有每个目标模式的标志。当所有标志都设置为 NULL 时,从表中删除该行。

于 2013-05-16T05:18:18.283 回答