我需要从源DB加载N(大约50个)表到目标数据库。每个表都与其他表不同(因此不同的元数据);我以为我可以使用父pkg来调用子节点,其中每个子节点都具有简单的结构,例如DFT,以映射要导入的表。想法1孩子pkg - > 1表 - > 1 dft +父母用来调用N pkg的配置表将是一个很好的设计猜测,因为这样,我可以达到模块化,我可以添加/删除表easiliy。糟糕的应用程序是将所有在一个单一的monolitic包装与DFT ... blah 你有任何想法/例子来解决这种情况吗? 马里奥
答案 0 :(得分:4)
我已成为使用biml来解决这些问题的粉丝。
假设所有内容都排成一列,您最终会得到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消耗,内存消耗和整体输出)。