如何提高基于SCN的查询性能?

时间:2013-05-15 12:44:15

标签: oracle oracle10g

在Oracle数据库中有一个pseudocolumn which's called ora_rowscn。如果它被检索,它会显示该行的最新更改的SCN(正如文档中所述)。

还有一个rowdependencies CREATE TABLE选项,用于为每一行打开SCN存储,而不是整个数据块(默认情况下)。

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

让我们考虑这个例子:

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

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

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

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

    以下任何架构的查询都在这里:

    查询1:

    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编制索引。

    问题:提高查询效果的方法有哪些?

2 个答案:

答案 0 :(得分:7)

您无法索引ora_rowscn。因此,查询1的最佳计划是FULL TABLE SCAN

由于这是不可接受的,您必须使用其他标记,例如last_updated date列。此列是可索引的,但您必须更新它。您可以使用轻量级触发器自动执行此更新。

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

答案 1 :(得分:0)

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

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

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

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

编辑:

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