`
shiren1118
  • 浏览: 133498 次
  • 性别: Icon_minigender_1
  • 来自: 吉林
社区版块
存档分类
最新评论

ETL调度原理浅析及最佳实践

    博客分类:
  • db
阅读更多

ETL 调度原理浅析及最佳实践

前言:

最早的调度应用是 unix crontab

 

最早的 ETL 规范是 NCR SPSS 一起制定的,所以 NCR ETL Automation 的方式此后一直是业界效仿的原因 (SPSS climentine 严格意义上它讲不再是 etl 调度工具,而是数据挖掘工具 ) ,从原理上讲是一样的,换汤不换药,从无图形化到 c\s ,然后从 c\s b\s ,它可能有更多本质变化吗 ?

1 、首先看一下 ETL 作业可能有哪些?

最典型的执行脚本, perl 脚本, shell bat 脚本, java 脚本, plsql 这类封装多个或一个 sql 的脚本。

其次执行 SQL 或存储过程

可能还有一些文件操作,比如创建和删除文件或目录。在数据清洗,断点回复和日志维护的时候是非常有用的。

 

对于系统管理员来讲,最好的工具可能是 shell perl 了,最短的代码完成最多功能。而且很多东西不要模块化。

 

目前 ETL 现状来看,并没有特别规范的实现,或者特别有新意的东西, SourceForge 上的开源项目貌似也寥寥无几。曾经和一个老外聊天,他说他在用 ruby etl 工具,我当时就很不解,问他为什么用 ruby ruby perl 这样的脚本语言固化的模块是很少的,各自为自己,实现功能而已,无通用性,实非通用产品之解决方案。

 

 

2 ETL 调度可能的执行方式

NCR ETL Automation 的方式来看,有 2 种,第一种是回调 shell cmd 方式,第二种是通过以驱动连接的方式。典型的 perl DBI::DBD odbc jdbc 等。这里附带提一下受限的 sqlplus 猜想。

 

它的执行方式可以分为静态和动态执行。

静态执行和数据库客户端的执行是一样的,即 2.1 小节讲的方式。

动态执行与语言结合的一种执行方式,即 2.1 小节讲的方式。

2.1 、回调 shell cmd 方式

为什么会出现这种方式?首先看 2 个连接例子:

 

cmd 下连接 oracle 数据库。

Sqlplus pcat\ mypwd@dssdb

select sysdate from dual

 

cmd 下连接 db2 数据库,首先进入 db2cmd 命令控制台,然后

db2 connect to dssdb user db2inst1 using mypwd

db2 select current date from sysibm.dummy1

 

这种方式可能是我们操作数据库最直接的方式。从上面 2 种不同的数据库来看,首先都是获得数据库连接,然后发送 sql 交给数据库来执行。(不止此 2 种数据库, mysql hsqldb derby ,包括 SqlServer 都可以在命令行下操作)。

 

优点:简单,直接,效率高,可以利用更多的数据库特性。

这种方式可以让 sql 预编译,静态 sql 比动态 sql 有优势的。

 

缺点:安全性比较低。我们可以看到上面的例子里用户名密码是暴露出来,这东西很可怕,尤其像移动这类的企业,对非常超级重视。

 

弥补缺点的方式:比如令牌环,比如把用户名和密码做成加密文件,用的时候再解密。

2.2 、以驱动 driver 方式开发

驱动是啥?

是一个应用(也可以说是语言级的)和数据库之间的桥。

 

举个例子《小王子》一书,被翻译成多国语言。这里的《小王子》就是数据库,翻译的人就是驱动,它兼通 2 者。

 

下面举一个 perl dbi 官方文档中的一个例子:

  

#!/usr/local/bin/perl





  

use



 DBI



;





  

use



 DBD::DB2::Constants



;





  

use



 DBD::DB2



 qw($attrib_int $attrib_char $attrib_float





                  

$attrib_date $attrib_ts)



;



  

# an extraneous example of the syntax for creating a new





  

# attribute type





  

$attrib_dec



 =



 {



 %$attrib_int



,





                 

'db2_type'



  

=>



 SQL_DECIMAL



,





                 

'SCALE'



     

=>



 2



,





                 

'PRECISION'



 =>



 31



 };





  

#$DBI::dbi_debug=9; # increase the debug output





  

# Open a connection and set LongReadLen to maximum size of column





  

$dbh



 =



 DBI



->



connect



(



"dbi:DB2:sample"



,



""



,



""



,



 {



 LongReadLen



 =>



 102400



 }



 );





  

if



 (!



defined



(



$dbh



))



 {



 exit



;



 }





  

# Note in the following sequence, that the statement contains





  

# no parameter markers, which makes the execution sequence





  

# just prepare and execute.





  

$stmt



 =



 "SELECT empno, photo_format FROM emp_photo WHERE





            

photo_format = 'gif';"



;



  

$sth



 =



 $dbh



->



prepare



(



$stmt



);





  

$sth



->



execute



();





  

# $row[0] is the empno from the database and $row[1] is the





 

熟悉 java 的朋友可能都觉得熟悉,其实 php mysql 也这么回事,殊途同归,只是方式而已。 Perl oo php 还真挺像的。

 

这种方式和语言结合的更加密切。他可以借助语言的 for 等来实现一些遍历操作(注:纯 SQL 是可以实现的,不过方式不太一样,希望大家别拿 plsql 说事, sql 的方式是多次关联,而不是说 plsql for 等。 plsql 已经算一门语言了,不是标准 sql )。

 

但是这里边有一个问题,通过驱动的执行的 sql 都是不能预编译,也就是他们属于动态 sql ,从效率上讲肯定是比静态 sql 低的。还有一个事要说, oracle db2 都支持一种驱动式的静态编译,是一个叫 SQLJ 的东西,有兴趣的可以去看看。

 

大多数人都是不区分动态 sql 和静态 sql 的概念的,大家对效率的看法过于偏重数据库本身。不太重视 sql 本身的业务逻辑,其实不细比较也看不出来。《 the art of SQL 》是一部非常不错的书。

2.3 sqlplus 猜想

这里的猜测是指 cmd 下的 sqlplus ,而不是图形化客户端的那个。

 

如果大家熟悉 windows 编程,可能知道 windows 也是有一个 shell 的, dos 命令和 windows shell 是完全不一样的,我猜测 sqlplus 是直接扩展 windows shell ,屏蔽了 dos 命令,不过 f 开头的快捷键还是可以使用的。

 

这个是可以考虑用来实现作业调度的。但是问题来了,跨平台是受限的,如果只是在 windows 下调用是没有问题的。

3 、典型的 shell cmd 回调方式举例

3.1 perl 实现方式

Perl 的实现方式其实是很优雅的。在 3.1.1 小节里会有分析。 Perl 处理 oracle Teradata db2 的原理是一样的,下面给出 2 种实现。

3.1.1 perl 连接 oracle 的实例

##########################################################################

# Description : run Oracle Command call the sqlplus to execute sql

# Input       : String sql

# Output      : None

# Example     :

#             my $sql = "sqlplus system/sang@dssdb;

#                                              select sysdate from dual;    

#                                            ";

#                          runOracleCommand($sql);

##########################################################################

sub runOracleCommand

{

         my ($cmd)=@_;

        

         my $rc = open(SQLPLUS, "|sqlplus");

         unless ($rc) {

                   print("Could not invoke CMD command");

                   return -1;

         }

         print SQLPLUS <<ENDINOUT;

                            $cmd

ENDINOUT

         close(SQLPLUS);

         my $RET_CODE = $? >> 8 ;

         print "RET_CODE,$RET_CODE";

}

 

分析一下:

         my $rc = open(SQLPLUS, "|cmd");

         上面的语句是回调的核心。为什么说它优雅呢? 先看它的过程,首先调用 sqlplus ,然后把 sql 传给 sqlplus ,有 sqlplus 来执行。这里面就有一个类 unix 管道的概念,后面定义的东西回调给 sqlplus ,作为 sqlplus 的输入,是不是很像呢?

         补充一下,这段程序是可以跨平台的。

         在集群的环境下,在不同的主机上,资源共享,但是 perl 环境不共享,这是当年遇到的一个问题,提醒自己复习一下。

 

3.1.2 perl db2

这个的执行方式和上面 3.1.1 的方式是一样的,其实这是从我根据 IBM DB2 安装的 sample 里的 perl 脚本的方式,自己把 NCR ETL Automation 封装成一个 pm 中的一段。这里是节选,不能直接运行的

DB2Util.pm 这个东西我还真觉得挺帅的,比如容错处理,共享连接,出错回滚等功能是河北移动,包括华为那边人( 2 OCP ,硕士)都没弄成来的,哈哈,沾沾自喜一下。

##########################################################################

# Description : execute DB2 SQL command .this is static SQL

#               actually,we use db's command to execute SQL.

# Input       : sql

# Output      : the executed return code.

# Example     :

#                                                               my $sql="insert into mk_vsdm.a values(13);";

#                                                               ETL::run_db2cmd($sql);

# TODO        : 虽说此方法应该有返回值,但是不知道为什么没有返回来?待改。

###########################################################################

sub run_db2cmd

{

#print "execute run_db2cmd()\n";

  my $rc = open(DB2CMD, "| db2 -mtvsp-");  # 执行失败不可继续建表或视图

  # To see if DB2CMD command invoke ok?

  unless ($rc) {

    print "Could not invoke DB2CMD command/n";

                   return -1;

         }

 

print DB2CMD <<ENDINOUT;

----------------------------------------------------------

----------------------------------------------------------

CONNECT TO HEBdw USER $db_user USING $db_password;

-----------------------------------------------------------

-----------------------------------------------------------

------------------SQL 语句开始 -----------------------------

-----------------------------------------------------------

  $sql

-------------------------------------------------------

-------------------------------------------------------

CONNECT RESET;

TERMINATE;

------------------------------------------------------

----------------SQL 语句结束 -------------------------

------------------------------------------------------

ENDINOUT

 

   close(DB2CMD);

          

         my $RET_CODE = $? >> 8 ;

  if ( $RET_CODE == 0 or $RET_CODE == 1 )

  {

                   showTime();

                   myStatusLog("execute sucess");

    return $SUCCESS;

  }

  elsif ( $RET_CODE == 2 )

  {

    showTime();

                   myStatusLog("execute sucess");

    print  " 加载文件 $sql 告警 :$RET_CODE \n";

    return $SUCCESS; 

  }

    else

  {

    showTime();

    print  " 加载文件 $sql 发生错误 ! 错误代码 :$RET_CODE \n";

    return $FAILURE;

  }

};

 

3.2 Java 实现方式

Java 来实现这个,其实还是有优势的,它最开始设计的时候就是为了跨平台,所以用 java 来做是非常好的。而且对于 java 的效率, javaEE 应用来看,采用 java 来做是非常合适的。

 

我说 java 有优势,不是和 perl 比较,各有优点,没法去比的。 Perl 处理单个脚本绝对是王者,但是讲到 OO ,这个是 java 的优势。而且 perl 写的 cgi 脚本和 java servlet/jsp 来比就差太多了,不是一个辈分的东西。

 

给出一段实际代码:

       try {

           Runtime .getRuntime ().exec( "dir" );

       } catch (IOException e) {

           e.printStackTrace();

       }

所有的对 cmd shell 的调用都是这种方式。

 

其实咱公司的数据集成平台中 ETL 部分,也肯定是采用这种方式。原理肯定是一样的。 Java 在语言级屏蔽了 shell cmd 的差异,省去了不少麻烦。

 

这样实现是没问题的,不过有很多问题要自己处理,其实 ant 的底层也是这么玩的,那么为什么不投机取巧呢?这个在后面的最佳实践中有说明。

 

3.3 、比较 crontab perl java 方式

crontab perl 都是进程级别的,建一个 job 就是一个进程,华为的那边 6 power6 服务器,就给 ETL Automation 开了 8 个进程,不知何故,猜测是性能消耗比较大。

java 里是线程,在 java5 以后有现成的线程池可以利用,效率更高。

 

4 、作业调度时间处理方式

上面讲的实际是 ETL 中执行方式。在 ETL 调度中有 2 大部分,一部分是上说过的执行方式,另一部分是触发方式。

 

所谓触发方式,就是某个时间触发某个作业的方式。常见的有日触发方式、月触发方式和临时触发。

 

触发最重要是时间处理。最典型的应用时 unix crontab 。指定要执行的 shell 6 个已空格来连接的时间表达式。这个表达式是通用表达式,它可以准确的表示某一天,某几天,执行多少次。它的灵活使他在简单应用或者系统管理员使用的非常多。

 

事实上,这种通用时间表达式确实是行业内的最佳实践。在 java 世界里开源工具 quartz 就有这种 cron  expression ,实现的非常相似。

 

待做

这里可以详细的解说一下表达式原理。

 

 

 

5 、给出作业调度的最佳实践(例子待完成)

我这个身份写这个,说实话,底气不足。像洪永这样的大先生,我是肯定比不过的,不过能抛砖引玉,对我,对公司来讲也都是好事。

 

5.1 Ant 来定义任务

Ant java 里著名的自动化构建工具。它通过 build.xml 来保存 target 信息,然后在命令行下,输入 ant + target 名称,通过这种方式来执行 target

Target 是什么东西?

分解来看,它本身是一个 task ,所以他的配置可能没有外参,但大多是有内参的。

 

 

1 、区分几个核心概念

    -- task

    -- Target

    -- Job

 

5.1.1 、任务 -task

 

这是 ant 里面的概念,其实一个任务就是完成一件事,可以使用 ant 的默认 task

当然 ant task 是可以定义的,所以给我们提供了足够的扩展性

比如:建立一个目录,删除一个文件,执行一个脚本,执行一段 SQL

 

5.1.2 、目标 -target

Ant 中,一个 target 由多个 task 组成,它指定的是一连串的 task

可以说一个 target 是一个流程,可以完成多个任务

 

例如:执行脚本的时候需要一个文件夹,执行完成的时候我想移动日志文件

<target>

    <task name=1>

       创建文件夹

    </task>

    <task name=2>

       执行脚本

    </task>

    <task name=3>

       移动日志文件

    </task>

</target>

 

说明: ant 执行 build.xml 中的就是 target ,只不过 target 还有其他配置,所以才有 job 层的抽象

 

5.1.3 、作业 -job

作业有 2 点需要实现: job dependency job stream

这是根据 NCR ETL Automation 的思想考虑的。 NCR SPASS 合订的规范也应该是这样的

很明显 job 是由一个到多个 target 实现,

出于上面考虑:作业划分为实作业和虚作业

    - 实作业:即所谓的 target ,而且是单个 target ,详见 1.2

    - 虚作业:即我们真正调用的作业

 

    本小节重点是虚作业。

    在定义 target 的时候,它的内部参数有个 depends ,它的值是多个 target 名称 , 以逗号分隔。

    下例来自 tomcat sample 应用:

      <target name="dist " depends="compile,javadoc "

               description="Create binary distribution">

   

        <!-- 在虚作业里,这部分 task 是可选的 -->

           <mkdir   dir ="${dist.home}/docs "/>

           <copy    todir ="${dist.home}/docs ">

             <fileset dir ="${docs.home}"/>

           </copy>

      

           <jar jarfile ="${dist.home}/${app.name}-${app.version}.war"

                basedir ="${build.home}"/>

        <!-- end define task-->

      </target>

    如上所示: depends 解决我们的 job depends ,原因是执行 dist 的时候会按顺序调用 complie javadoc

    job depends compile javadoc -- 2 target

    job Stream 这个是按 depends 顺序的, compile 在前,然后是 javadoc

   

    <!-- [if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:PunctuationKerning/> <w:DrawingGridVerticalSpacing>7.8 磅</w:DrawingGridVerticalSpacing> <w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery> <w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery> <w:ValidateAgainstSchemas/> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:Compatibility> <w:SpaceForUL/> <w:BalanceSingleByteDoubleByteWidth/> <w:DoNotLeaveBackslashAlone/> <w:ULTrailSpace/> <w:DoNotExpandShiftReturn/> <w:AdjustLineHeightInTable/> <w:BreakWrappedTables/> <w:SnapToGridInCell/> <w:WrapTextWithPunct/> <w:UseAsianBreakRules/> <w:DontGrowAutofit/> <w:UseFELayout/> </w:Compatibility> <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel> </w:WordDocument> </xml><![endif]--><!-- [if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" LatentStyleCount="156"> </w:LatentStyles> </xml><![endif]--><!-- [if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:普通表格; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman"; mso-ansi-language:#0400; mso-fareast-language:#0400; mso-bidi-language:#0400;} </style> <![endif]-->

 

5.1.4 、三者之间关系

                             -task 1..n

             --target 1..n -[ 

      -- 实作业 -|

作业 -| 

      -- 虚作业 -|

              --target 1..n -[

                                -task 1..n

     

     

      job  (0..n)  job  (1..n)   target   (1..n)   task

     

     

     

 

更明确点讲,虚作业是我们在调度过程中所谓的作业。

而实作业是 target 。虚作业是带了依赖关系的 target

依赖关系可以确定依赖还可以确定调度顺序,所以有依赖关系的才是我们在调度过程中所谓的作业 .

Task ant 的概念,一个 target 由多个 task 组成,这些 task 可以随意扩展,也可以随意定义。这给我们的系统提供足够的可扩展空间。

 

2 、区分 build.xml 中的属性与模板

target1

<target name="help">

  <exec executable="cmd">

    <arg value="/c"/>

    <arg value="ant.bat"/>

    <arg value="-p"/>

  </exec>

</target>

 

 

 

Co

分享到:
评论
2 楼 kitleer 2014-11-03  
原理比较浅显易懂。
最佳实践有些晦涩。
unix java php xml

采用TASKCTL来实践会不会容易些?
1 楼 que1 2011-03-10  
学习了,哈哈,ETL还是蛮有意思的。

相关推荐

    基于MapReduce的分布式ETL调度优化方法.pdf

    总体而言,分布式ETL调度优化是一个涉及多个层面的问题,不仅需要考虑数据的类型和节点的计算能力,还需要综合考量作业大小及类型,并且要考虑到系统的吞吐率和响应时间。而MapReduce作为一种高效的并行处理模型,为...

    ETL本质原理和关键技术介绍

    Etl本质原理和关键技术介绍 ETL(Extract, Transform, Load)是一种数据整合解决方案,旨在将来自不同数据源的数据提取、转换和加载到目标系统中。在数据仓库系统中,ETL扮演着关键的一环,它不是一次性的工作,...

    asofdate-etl一个企业级ETL调度系

    这是一个企业级ETL调度系统, 在成熟的spring框架基础上,实现ETL调度服务. 权限管理部分,采用asofdate项目,asofdate项目采用golang开发,asofdate-etl采用java重写了asofdate后台api,由于两个项目都是采用jwt加密用户...

    PDI最佳实践etl开发必备手册

    ### PDI最佳实践ETL开发必备手册 #### 概览 本手册旨在为设计与构建Pentaho Data Integration (PDI)转换与作业提供最佳实践指南。遵循这些指南能够实现最大的速度、重用性、可移植性、可维护性和知识传递效果。本...

    etl原理.doc

    - **资源调度**:根据业务需求和系统负载情况,合理安排ETL作业的执行时间,避免与其他高并发业务冲突。 4. **数据清洗**:异常数据清洗是ETL的重要环节,需要定义合适的清洗规则,确保数据质量。例如,可以设置...

    PBS:一种面向集群环境的ETL调度算法.pdf

    【PBS ETL调度算法概述】 PBS(Predictive-Based Scheduling)是一种面向集群环境的ETL(Extract-Transform-Load)调度算法,旨在提高数据抽取、转换和加载过程的执行效率。随着企业对大数据分析需求的增长,传统的...

    基于ISE算法的分布式ETL任务调度策略研究.pdf

    在当前信息技术领域中,随着数据量的增长和数据仓库的规模不断扩大,数据集成任务也随之增多,单机调度已经无法高效应对大量复杂的ETL(Extraction, Transformation, Loading)任务。为了解决ETL任务调度效率低下、...

    ETL_调度系统技术方案说明书

    参考资料则可能包含相关技术标准、行业最佳实践和先前的项目文档。 **系统需求分析** 需求分析是项目启动的关键阶段,它明确了系统的功能边界和性能要求。需求分析的目标是明确系统的目标和任务,如自动调度、错误...

    ETL调度工具TASKCTL(免费版)

    综上所述,TASKCTL作为一款强大的ETL调度工具,凭借其企业级的性能、稳定性及易用性,为大数据环境下的数据处理提供了可靠的支持。通过Taskctl 4.0 Setup.exe的安装,以及readme.txt的辅助,用户可以便捷地将TASKCTL...

    ETL设计与开发实践

    本实践指南将深入探讨ETL的设计与开发过程,旨在帮助读者掌握ETL的工作原理、最佳实践以及常见问题的解决方案。 一、ETL概述 ETL过程可以分为三个主要阶段: 1. 抽取(Extract):从源系统中提取数据,这些源可能...

    一种改进的分布式ETL作业调度方法实现.pdf

    分布式系统是当前IT行业中的一个重要研究方向,尤其是在大数据和云计算技术快速发展的今天,...在实际的应用中,企业可以根据自身业务需求和数据特点,对这套作业调度方法进行适当的调整和优化,以达到最佳的应用效果。

    粒子群算法在分布式ETL任务调度中的应用.pdf

    在了解“粒子群算法在分布式ETL任务调度中的应用”这一主题之前,需要先明白几个关键概念:分布式ETL、任务调度以及粒子群优化算法。 分布式ETL(Extraction, Transformation, Loading)是数据仓库构建过程中的核心...

    BI ETL ELT Kettle 基础知识中文文档汇总

    ETL_调度系统技术方案说明书_V1.0.pdf ETL中的数据清洗设计.pdf ETL交流.pdf ETL培训.ppt ETL工具比较.pdf ETL应用浅析.pdf ETL开发实施中质量保证的关键要素V1.0.pdf ETL数据增量抽取方案.pdf ETL数据集成...

    国产自动化运维ETL批量调度平台 TASKCTL 8.0 安装包

    TASKCTL是ETL调度领域专业的调度产品,适用于各行业的企业级、项目级ETL调度平台建设。此版是在C/S桌面客户端的基础上,TASKCTL 重新构建了一套基于web浏览器的B/S版本; 其中 TASKCTL 基础版的设计核心是以开发...

    ETL_调度系统技术方案说明书_V1.0

    本文档旨在详细介绍ETL调度系统的技术方案,包括基础架构、模型设计、模块设计及流程设计等内容。目的是为开发人员、使用人员和维护人员提供全面的技术指南,帮助他们更好地理解和应用该系统。 #### 二、系统需求...

    ETL应用浅析

    ### ETL应用浅析 #### 一、引言与背景 随着信息技术的发展,企业越来越重视数据的价值。然而,数据仓库系统作为数据管理的核心组件之一,却面临着诸多挑战。特别是由于历史原因,许多企业的业务系统是在不同的时期...

    ETL.rar_etl

    首先,"ETL应用浅析.doc"文档很可能是对ETL技术的详细解析,包括ETL的工作原理、主要步骤、工具选择以及在实际项目中的应用场景。在ETL过程中,提取(Extract)阶段是从数据库、日志文件或其他数据源获取原始数据;...

    ETL增量原理

    总的来说,ETL增量处理是提升数据处理效率的关键技术,理解其原理并熟练运用,对于构建高效、稳定的数据处理系统至关重要。在具体实践中,需结合业务需求和数据源特性选择合适的方法,并做好详尽的规划和测试,以...

Global site tag (gtag.js) - Google Analytics