ODI中删除数据的处理

一、前提知识:
数据从源数据库向数据仓库抽取时,一般采用以下几种方式:

  • 全抽取模式
    如果表的数据量较小,则可以采取全表抽取方式,以TRUNCATE/INSERT方式进行数据抽取。
  • 基于时间戳的抽取模式
    如果源数据表是不可更新的数据(如大多数事务处理数据)或者是不可删除数据(只能失效历史记录的情况),则根据变更时间戳,抽取最新变更的数据进行同步。
  • 日志分析
    如果没有更新时间戳,或者源数据存在删除的情况,则可以进行日志分析,来执行最新数据变更的同步。

说明:时间戳的方式如果要处理删除数据的情况,需要在源表创建触发器来捕获删除的记录。
ODI在数据抽取方面,添加了CDC(Changed Data Capture)的功能,并且包含两种方式,一种是在源数据库表上增加触发器来捕获新增、修改和删除的数据到日志表中。另一种是通过对日志的挖掘(Oracle的Log Miner和IBM DB2/400)。但是ODI的CDC,必须要求源表有主键。
二、删除数据的问题引入
当我们开始使用ODI来进行CDC方式的数据同步时,一切都正常,删除的数据也可以正确的同步到目标数据库。接着,因为业务需求,我们只需要同步部分数据到目标数据库,也就是为源数据表加上过滤,这样问题就出来了,新增和修改的数据都能正确的同步到目标数据库,而源数据表删除的数据,经过ODI Interface执行之后,目标数据表中还存在。
经过检查,Interface在装载数据时查询日志视图,而日志视图是日志表与源表的外连接,其结果是删除的记录在视图中只有主键,其余的字段都为空,这样基于日志视图上的过滤,必然导致删除的数据被过滤掉。以下是ODI创建的对象脚本示例:

数据源日志视图jv$qp_list_lines
create or replace view soau.jv$qp_list_lines as
SELECT decode(targ.ROWID, NULL, 'D', 'I') jrn_flag,
       jrn.jrn_subscriber jrn_subscriber,
       jrn.jrn_date jrn_date,
       jrn.list_line_id list_line_id,
       targ.creation_date creation_date,
       targ.created_by created_by,
       ...
FROM (SELECT l.jrn_subscriber jrn_subscriber, l.list_line_id list_line_id, MAX(l.jrn_date) jrn_date
FROM soau.j$qp_list_lines l
WHERE l.jrn_consumed = '1'
GROUP BY l.jrn_subscriber, l.list_line_id) jrn,
soau.qp_list_lines targ
WHERE jrn.list_line_id = targ.list_line_id(+)

ODI Interface创建用于装载数据的的临时视图
create or replace view
SOAU.C$_0QP_LIST_LINES
(
C1_LIST_LINE_ID,
C2_CREATION_DATE,
C3_CREATED_BY,
...
JRN_SUBSCRIBER,
JRN_FLAG,
JRN_DATE
)
as select
QP_LIST_LINES.LIST_LINE_ID,
QP_LIST_LINES.CREATION_DATE,
QP_LIST_LINES.CREATED_BY,
...
JRN_SUBSCRIBER,
JRN_FLAG,
JRN_DATE
from SOAU.JV$QP_LIST_LINES QP_LIST_LINES
where (1=1)
And (QP_LIST_LINES.LIST_LINE_TYPE_CODE IN ('PLL', 'PBH'))
And (QP_LIST_LINES.END_DATE_ACTIVE is null or trunc(QP_LIST_LINES.END_DATE_ACTIVE) > trunc(sysdate))
And (QP_LIST_LINES.PRICING_PHASE_ID = 1)
And (QP_LIST_LINES.QUALIFICATION_IND IN (4, 6, 20, 22))
AND JRN_SUBSCRIBER = 'ERP-FK' /* AND JRN_DATE < sysdate */


Interface在执行集成时,将数据从视图SOAU.C$_0QP_LIST_LINES插入到flow table(flow
table是Interface处理的位于目标中间表,数据的同步最终从flow
table到目标数据表),由于该视图已经执行了过滤,删除的数据就无法插入到flow table,导致删除的数据最终无法写入目标。
三、问题解决过程
因为数据在源头就被过滤了,所以必须保证数据在源头不被过滤,而Interface可以支持在源、Staging、目标来执行处理,那么就来做各种测试:
1、将数据过滤移到Staging
经过测试发现,虽然在装载数据时,包含了删除的记录,但是在集成阶段,数据插入flow table时,由于除了主键,其余字段都为空,所以删除的数据同样被过滤掉了。
2、将数据过滤移到目标
经过测试,当我们将过滤移到目标时,删除的数据被正确的同步到了目标表。那只要将过滤移到目标,就可以解决问题了?
3、新问题的出现
实际上数据插入flow table后,从flow table到目标表,没有执行任何过滤处理,所有数据都会被同步到目标数据表。这样我们需要排除的数据也写入了目标表,说明这个方式失败。
4、启用模型中目标表的过滤
在ODI Designer中,编辑Model下的表,添加过滤,然后将Interface中对源数据的过滤移除,执行Interface发现,数据正确的插入到了目标表。但是这种方式和前一种方式相同,都是把所有变化的数据都从源取到目标中,存在一定的性能问题。
5、最终的方式
经过研究,还是觉得修改ODI原来的LKM最为实际,只需要把从日志视图的取数的视图代码修改,修改为原来的视图代码UNION删除的记录即可。
修改后的Create view on source代码如下:

create or replace view <%=odiRef.getObjectNameDefaultPSchema("L", "" , "W")%><%=odiRef.getInfo("COLL_NAME")%>
(
<%=odiRef.getColList("", "[CX_COL_NAME]", ",/n/t", "", "")%>
)
as select <%=odiRef.getPop("DISTINCT_ROWS")%>
<%=odiRef.getColList("", "[EXPRESSION]", ",/n/t", "", "")%>
from <%=odiRef.getFrom()%>
where (1=1)
<%=odiRef.getFilter()%>
<%=odiRef.getJrnFilter()%>
<%=odiRef.getJoin()%>
<%=odiRef.getGrpBy()%>
<%=odiRef.getHaving()%>

<%if(!odiRef.getJrnFilter().equals("")){%>

UNION

select <%=odiRef.getPop("DISTINCT_ROWS")%>
<%=odiRef.getColList("", "[EXPRESSION]", ",/n/t", "", "")%>
from <%=odiRef.getFrom()%>
where (1=1)
<%=odiRef.getJrnFilter()%>
AND JRN_FLAG='D'
<%=odiRef.getJoin()%>
<%=odiRef.getGrpBy()%>
<%=odiRef.getHaving()%>

<%}%>
四、插曲
在问题有了解决方案之后,向Oracle提Tar,经过数次沟通,并最终在OWC演示的情况下,确认为KM的Bug。
不过Oracle又提供了一种处理方法,这种方法不需要修改LKM,但是看上去感觉总有点不那么好:在Interface中的每个Filter代码中,加入" OR JRN_FLAG = 'D'",这样就可以保证日志表中删除的记录一定不会被过滤掉。

本文转自:http://www.itjaj.com/viewthread.PHP?tid=4590&extra=page%3D1%26amp%3Bfilter%3Dtype%26amp%3Btypeid%3D88

ODI中删除数据的处理的更多相关文章

  1. NHibernate 中删除数据的几种方法

    今天下午有人在QQ群上问在NHibernate上如何根据条件删除多条数据,于是我自己就写了些测试代码,并总结了一下NHibernate中删除数据的方式,做个备忘.不过不能保证囊括所有的方式,如果还有别 ...

  2. 总结NHibernate 中删除数据的几种方法

    今天下午有人在QQ群上问在NHibernate上如何根据条件删除多条数据,于是我自己就写了些测试代码,并总结了一下NHibernate中删除数据的方式,做个备忘.不过不能保证囊括所有的方式,如果还有别 ...

  3. SQL语句的使用,SELECT - 从数据库表中获取数据 UPDATE - 更新数据库表中的数据 DELETE - 从数据库表中删除数据 INSERT INTO - 向数据库表中插入数据

    SQL DML 和 DDL 可以把 SQL 分为两个部分:数据操作语言 (DML) 和 数据定义语言 (DDL). SQL (结构化查询语言)是用于执行查询的语法. 但是 SQL 语言也包含用于更新. ...

  4. GDAL书籍中删除数据勘误(C#语言)

    GDAL书籍中关于C#版本删除数据的时候,不能完全删除数据,由于我对C#不了解导致代码有点问题,非常感谢@Bingoyin指出并给出修改方案.此外对于栅格图像的删除.重命名,矢量数据的删除和重命名都有 ...

  5. MySQL中删除数据的两种方法

    转自:http://blog.csdn.net/apache6/article/details/2778878 1. 在MySQL中有两种方法可以删除数据: 一种是delete语句,另一种是trunc ...

  6. SQL语句中—删除数据

    老大------drop 出没场合:droptable tb --tb表示数据表的名字,下同 绝招:删除内容和定义,释放空间.简单来说就是把整个表去掉.以后要新增数据是不可能的,除非新增一个表 老二- ...

  7. map在遍历数据的过程中删除数据不出错

    // Iterator<Map.Entry<String,Long>> entries = Map.entrySet().iterator();                 ...

  8. telerik:RadGrid 表格中删除数据

    <telerik:RadGrid OnItemCommand=" Height="490px" Culture="zh-CN" CssClass ...

  9. Sql Server删除数据表中重复记录 三种方法

    本文介绍了Sql Server数据库中删除数据表中重复记录的方法. [项目]数据库中users表,包含u_name,u_pwd两个字段,其中u_name存在重复项,现在要实现把重复的项删除![分析]1 ...

随机推荐

  1. jsp页面适应手机页面

    <meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scal ...

  2. 图的最短路径问题————树上奶牛(tree.cpp)

    和往常一样,继续从题目引入 树上奶牛 (tree.cpp) [题目描述] 农夫John的奶牛不是住在地上而是住在树上的QWQ. 奶牛之间需要串门,不过在串门之前他们会向John询问距离的大小.可是Jo ...

  3. Linux命令--链接文件的那些事

    linux 链接ln的使用 linux操作系统下ln的使用方式: ln [option] source_file dest_file #source_file是待建立链接文件的文件,dest_file ...

  4. 浏览器文档播放Shockwave Flash 插件问题

    浏览器被提示shockwave flash crashed怎么办?在使用浏览器的时候经常被提示shockwave flash crashed,flash插件崩溃,网页就会出现一些无法显示的文件,下面绿 ...

  5. Eclipse用link方式安装插件

    其实eclipse安装插件更方便的方法就是直接扔到eclipse目录下的dropins文件夹,但如果插件比较多或者大的话,会让eclipse变得臃肿.下面介绍的用link方式可以避免这样的问题. 用l ...

  6. SQLServer 2008 R2 清空日志文件

    USE [master]GOALTER DATABASE FH2_SJH SET RECOVERY SIMPLE WITH NO_WAITGOALTER DATABASE FH2_SJH SET RE ...

  7. PHP简易计算器方法1

    <?phpheader("content-type:text/html;charset=utf-8");session_start();?><!DOCTYPE h ...

  8. C# 单向链表数据结构 (一)

    单向链表数据结构是有节点组成,每个节点包含两部分,第一部分为存储数据,第二部分为指向下一个节点的指针.注意,有两个特色的节点,分别为“头节点”和“尾节点”,头节点本身没有数据,只存储下一个节点的指针, ...

  9. 【OpenGL游戏开发之三】OpenGl核心函数库汇总

    OpenGl核心函数库 glAccum 操作累加缓冲区 glAddSwapHintRectWIN 定义一组被SwapBuffers拷贝的三角形 glAlphaFunc允许设置alpha检测功能 glA ...

  10. c语言结构体排序示例

    设计性实验编程实现对学生成绩表的相关信息排序.实验要求:⑴ 建立一个由n个学生的考试成绩表,每条信息由学号.姓名和分数组成.⑵ 按学号排序,并输出排序结果.⑶ 按分数排序,分数相同的则按学号有序,并输 ...