从源到目标服务器加载N个表的最佳实践

时间:2013-11-26 16:19:07

标签: sql ssis

我需要从源DB加载N(大约50个)表到目标数据库。每个表都与其他表不同(因此不同的元数据);我以为我可以使用父pkg来调用子节点,其中每个子节点都具有简单的结构,例如DFT,以映射要导入的表。想法1孩子pkg - > 1表 - > 1 dft +父母用来调用N pkg的配置表将是一个很好的设计猜测,因为这样,我可以达到模块化,我可以添加/删除表easiliy。糟糕的应用程序是将所有在一个单一的monolitic包装与DFT ... blah 你有任何想法/例子来解决这种情况吗? 马里奥

3 个答案:

答案 0 :(得分:4)

我已成为使用biml来解决这些问题的粉丝。

  1. 下载并安装BIDS Helper
  2. 将新的biml文件添加到现有SSIS项目
  3. 禁用Visual Studio对XML文件的自动修复。请参阅Overcoming BimlScript Copy and Paste Issues in Visual Studio
  4. 将此代码粘贴到该Bimlscript.biml文件
  5. 修复源和目标连接字符串(第8行和第9行)以指向正确的服务器,如果SQLNCLI11.1对于您的SQL Server版本不正确,则更改提供程序类型
  6. 右键单击biml文件并选择“生成SSIS包”
  7. 假设所有内容都排成一列,您最终会得到29个包,其中包含单个数据流任务,从源到目标(基于SSIS变量)。

    <#@ template language="C#" hostspecific="true" #>
    <#@ import namespace="System.Data" #>
    <#@ import namespace="System.Data.SqlClient" #>
    <#@ import namespace="System.IO" #>
    <Biml xmlns="http://schemas.varigence.com/biml.xsd">
    <!--
    <#
        string connectionStringSource = @"Server=localhost\dev2012;Initial Catalog=AdventureWorksDW2012;Integrated Security=SSPI;Provider=SQLNCLI11.1";
        string connectionStringDestination = @"Server=localhost\dev2012;Initial Catalog=AdventureWorksDW2012_DEST;Integrated Security=SSPI;Provider=SQLNCLI11.1";
    
        string SrcTableQuery =     @"
    SELECT
        SCHEMA_NAME(t.schema_id) AS schemaName
    ,   T.name AS tableName
    FROM
        sys.tables AS T
    WHERE
        T.is_ms_shipped = 0
        AND T.name <> 'sysdiagrams';
    ";
    
        DataTable dt = null;
        dt = ExternalDataAccess.GetDataTable(connectionStringSource, SrcTableQuery);
    #>    
    -->
        <Connections>
            <OleDbConnection
                Name="SRC"
                CreateInProject="false"
                ConnectionString="<#=connectionStringSource#>"
                RetainSameConnection="false">
            </OleDbConnection>
            <OleDbConnection
                Name="DST"
                CreateInProject="false"
                ConnectionString="<#=connectionStringDestination#>"
                RetainSameConnection="false">
            </OleDbConnection>
        </Connections>
    
        <Packages>
            <# foreach (DataRow dr in dt.Rows) { #>
                <Package ConstraintMode="Linear"
                    Name="<#=dr[1].ToString()#>"
    
                >
                <Variables>
                    <Variable Name="SchemaName" DataType="String"><#=dr[0].ToString()#></Variable>
                    <Variable Name="TableName" DataType="String"><#=dr[1].ToString()#></Variable>
                    <Variable Name="QualifiedTableSchema"
                              DataType="String"
                              EvaluateAsExpression="true">"[" +  @[User::SchemaName] + "].[" +  @[User::TableName] + "]"</Variable>
                </Variables>
                <Tasks>
                    <Dataflow
                        Name="DFT"
                    >
                        <Transformations>
                            <OleDbSource
                                Name="OLE_SRC <#=dr[0].ToString()#>_<#=dr[1].ToString()#>"
                                ConnectionName="SRC"
                            >
                                <TableFromVariableInput VariableName="User.QualifiedTableSchema"/>
                            </OleDbSource>
                            <OleDbDestination
                                Name="OLE_DST <#=dr[0].ToString()#>_<#=dr[1].ToString()#>"
                                ConnectionName="DST"
                                KeepIdentity="true"
                                TableLock="true"
                                UseFastLoadIfAvailable="true"
                                KeepNulls="true"
                                >
                                <TableFromVariableOutput VariableName="User.QualifiedTableSchema" />                        
                            </OleDbDestination>
                        </Transformations>
                    </Dataflow>
    
                </Tasks>
                </Package>
            <# } #>
        </Packages>
    </Biml>
    

    此时,您只需要弄清楚如何协调程序包的执行。

答案 1 :(得分:2)

您可以使用SSIS中的执行SQL任务进行复制或直接从SQL代理执行。这假定模式已存在于目标数据库中。

DECLARE @tblname as varchar(50);
DECLARE @tblschema as varchar(50);
DECLARE @srcdb as varchar(12);
DECLARE @destdb as varchar(12);
DECLARE @tablesql as nvarchar(255);

SET @srcdb = 'MYSRCDB';
SET @destdb = 'MYDESTDB';

DECLARE tbl_cursor CURSOR FOR
SELECT table_schema, table_name FROM information_schema.tables where table_type = 'BASE TABLE'

OPEN tbl_cursor

FETCH NEXT FROM tbl_cursor INTO @tblschema, @tblname
WHILE @@FETCH_STATUS = 0
BEGIN

SET @tablesql = N'SELECT * into '+@destdb+'.'+@tblschema+'.'+@tblname+' FROM '+@srcdb+'.'+@tblschema+'.'+@tblname;
EXECUTE sp_executesql @tablesql

FETCH NEXT FROM tbl_cursor INTO @tblschema, @tblname
END

CLOSE tbl_cursor
DEALLOCATE tbl_cursor

答案 2 :(得分:1)

有很多因素会对选择的方案产生影响。

但总的来说:

对于行数相对较少的小型表,可以将多个源/目标放在单个数据流中

如果您有源/目的地的复杂ETL,那么为了清晰起见,最好将它们分别用于数据流任务

如果您需要定义执行顺序,则必须使用多个数据流任务,因为您无法控制单个数据流任务中多个源/目标的执行顺序。

每当您需要不同的事务隔离级别或行为时,您必须将它们放入单独的数据流中。

每当您不确定ETL对源系统的影响时,请将它们放在单独的数据流中,因为这样您将来可以更轻松地优化执行顺序。

如果您有大型表而不是将它们放入单独的数据流任务中,因为这将允许优化不同表的缓冲区大小并出于任何原因优化ETL过程

因此,如果你有相对较小的表和直接的源/目标映射,那么在单个数据流中有更多的源/目标是没有问题的。

在其他情况下,将它们放入单独的数据流中是更好或更必要的,因为它允许您从所有三个角度优化ETL过程:

对源系统的负载影响

加载对目标系统的影响

利用运行ETL进程的机器(CPU消耗,内存消耗和整体输出)。