在Oracle数据库中有一个pseudocolumn which's called ora_rowscn
。如果它被检索,它会显示该行的最新更改的SCN(正如文档中所述)。
还有一个rowdependencies
CREATE TABLE
选项,用于为每一行打开SCN存储,而不是整个数据块(默认情况下)。
所以,我正在使用此列的值来指示哪些行已更新,需要上传到另一个数据库。
让我们考虑这个例子:
架构T1
中有一个表S1
,其中包含数百万条记录(对于常规查询,桌面上的完整扫描无法承受)。
CREATE TABLE T1 {
A INTEGER PRIMARY KEY,
B VARCHAR2(100),
C DATE
}
/
有模式S2, S3, S4, S5..
,每个模式都有表格T2
。
CREATE TABLE T2 {
A INTEGER
}
/
T2
中只有一行,但T2.A
的值在不同的模式中可能有所不同。
因此,我需要在每个模式(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
编制索引。
问题:提高查询效果的方法有哪些?
答案 0 :(得分:7)
您无法索引ora_rowscn
。因此,查询1的最佳计划是FULL TABLE SCAN
。
由于这是不可接受的,您必须使用其他标记,例如last_updated
date
列。此列是可索引的,但您必须更新它。您可以使用轻量级触发器自动执行此更新。
查询1对索引列的性能取决于检索的行数。
答案 1 :(得分:0)
您关心的是,自您上次运行上传以来插入或更新了哪些行。
为什么不在表中添加标记,将每一行标记为“脏” - 即插入前触发器将其设置为“X”,而更新前触发器将其设置为“X”。
然后,编写上传过程以查询表中标志为非NULL的任何行,然后在成功时将标志设置为NULL。请注意,这意味着在上传过程中插入/更新的新行仍将正确标记,并在下次上传时将被选中。
如果插入/更新的行数与表中的总行数相比是一个非常小的比例,则该标志上的索引将是有用的,因为NULL标志将不会存储在索引中(即索引通常会小。
编辑:
需要更新多个模式的情况的等效解决方案是拥有一个单独的表,该表将保存已更改的行的ID。该表应具有每个目标模式的标志。当所有标志都设置为NULL时,从表中删除该行。