SQL Server Integration Services的10大最佳实践

原文出处:https://blogs.msdn.microsoft.com/sqlcat/2013/09/16/top-10-sql-server-integration-services-best-practices/sql

 

译:数据库

多少人据说过“SQL Server Integration Services(译注:如下简称SSIS)不能扩展”的传说?咱们要反问的是“你的系统是否有必要扩展到每秒可以处理超过450万行交易记录?”SSIS是能够适应最极端环境的高性能ETL平台。而且正如在SSIS ETL性能世界记录所记载,SSIS能够处理每秒450万规模的销售交易记录。缓存

1.SSIS是基于内存的数据管道,所以请确保全部的转换发生在内存中。服务器

在SQL Server的功能中加入SSIS的目的是提供一个有弹性且稳定的数据管道,以便于在内存中高效地执行逐行计算和数据校验。网络

SSIS自己的数据转换应该在内存中处理,然而数据抽取和载入阶段却会涉及磁盘(会产生相应的读写)。一旦数据转换操做溢出到磁盘上,ETL性能将会有显著降低。为了确保全部的转换都可以在内存中处理,请仔细构建包以分割并过滤数据。并发

确认包是否驻留在内存中的一个好办法是检查SSIS缓存池相关的性能计数器,它的初始值是0,超过0就意味着SSIS引擎开始切换到磁盘上。更多详情,请参考SSIS性能计数器二三事函数

2.根据资源使用的状况规划容量工具

SSIS的设计目标是在内存中高速逐行处理大量数据。所以,理解资源使用状况是很是重要的,好比CPU,内存,I/O,以及网络消耗。性能

CPU限制测试

当SSIS正在运行的时候,请设法搞清楚SSIS用了多少CPU,SQL Server总共用了多少CPU。若是SQL Server和SSIS安装在同一台机器上,那么后者就显得十分重要。由于一旦二者之间存在资源竞争,SQL Server每每会胜出——这会致使SSIS的数据转换操做溢出到磁盘上,而这会下降数据转换性能。

你感兴趣的性能计数器应该是Process / % Processor Time (Total)。衡量sqlservr.exe和dtexec.exe的这个计数器值。若是SSIS没法驱使CPU达到100%负载,这可能代表:

  • 应用程序竞争:例如,SQL Server占用了更多CPU资源,使CPU不能为SSIS所用。
  • 硬件竞争:一个常见的场景是你的磁盘I/O不够好或者没有足够的内存,没法应付要处理的数据量。
  • 设计上的限制:你的SSIS包没有利用到并行设计,而且/或者包使用了太多单线程任务。

网络限制

SSIS会尽你网络所能地传输数据。所以,搞清楚你的网络拓扑结构是很重要的,一样重要的是确保从源到目标之间的路径具备低延迟和高吞吐。

如下性能计数器能够帮你调整你的网络拓扑结构:

  • Network Interface / Current Bandwidth: 这个计数器会估算当前带宽。
  • Network Interface / Bytes Total / sec:这是每一个网络适配器上发送和接收的字节数。
  • Network Interface / Transfers / sec:显示每秒发生多少网络传输操做。若是这个值接近每秒40000IO,那么请考虑增长网卡并在网卡间使用teaming技术。

这些计数器可让你分析你的系统是否充分利用带宽。理解这点可让你经过使用千兆网卡,增长网卡数量,或者新增网络地址以恰当地规划网络容量。

I/O限制

若是你能确保SSIS已经最小化磁盘写入操做,SSIS只会在从源读取数据以及写入数据时接触到磁盘。而若是你的I/O性能太慢,读写(特别是写入)操做将成为性能瓶颈。

因为优化I/O超出了本文的范畴,请参考前期部署最佳实践。请注意,I/O系统的规格不仅有它的大小(例如“我须要10TB”)——也包括了它的速度(例如“我须要达到每秒20000IO”)。

内存限制

你须要搞清楚一个很重要的问题“个人包到底须要多少内存?”

对此,关键的性能计数器有:

  • Process / Private Bytes (DTEXEC.exe):当前SSIS使用的内存大小。这部份内存不能与其它进程共享。
  • Process / Working Set (DTEXEC.exe):SSIS分配的总内存大小。
  • SQL Server: Memory Manager / Total Server Memory:SQL Server分配的总内存大小。因为SQL Server能够经过AWE API分配内存,只有这个性能计数器能够准确反映SQL Server使用的内存大小。要更好地理解SQL Server内存分配机制,请参考Slava Ok的博客
  • Memory / Page Reads / sec:这表明系统的内存压力。若是这个指标持续在500以上,说明系统存在内存压力。

3.源系统抽取速度基线

你得搞清楚从源系统抽取数据的速度。毕竟,SSIS不可能优化得比源系统还快——好比说,你不可能比读取数据更快地进行数据转换。

你能够经过建立一个带“Row Count”数据流组件的包来测量源系统的速度。

 

你能够从命令行(DTEXEC)执行这个包并测量它的完成时间。也能够用SSIS日志输出来准确计算执行时间。你须要的速度,就是每秒传输了多少行:

Rows / sec = Rows Count / Time

根据这个基准速度,咱们就知道能够多快地从源抽取数据——这也是你转换数据的速度极限。要计算出这个速度,你能够尝试如下方法:

  • 升级驱动和驱动配置:针对网络,数据源,和磁盘I/O,请确保你的驱动已经升级到最新版本。一般你的服务器默认网络驱动并未针对网络进行过精确的优化,当吞吐量大的时候这会致使性能降低。要注意的是,对于64位系统,你可能在设计时用的倒是32位的驱动。请确保在运行时你用的是64位驱动。
  • 多重链接:为了克服驱动的限制,你能够尝试利用多重链接从数据源抽取数据。正如数据源能够处理并发链接同样,同时进行多重抽取能够提升吞量。若是并发致使了锁定或者阻塞问题,能够考虑分割数据源,并使你的包同时从多个分区抽取以分摊负载。
  • 多网卡:若是网络是性能性能瓶颈,而你已采用了千兆网卡和路由,那么一个可能的解决方案就是在每一个服务器上都使用多块网卡。要注意的是多网卡环境须要仔细配置,不然有可能会发生网络冲突。

4.优化SQL Data Source,Lookup transformations,和Destination。

 

当你在SSIS中执行SQL语句(正如上图所示的Data access mode对话框),是否在查询数据源时实现Lookup逻辑,或者修改某些表,一些标准的优化手段能够显著地提升性能表现:

  • 使用NOLOCK或者TABLOCK表提示以免锁定开销。
  • 为了优化内存消耗,只SELECT你确实须要的列。若是你SELECT一张表的全部列(例如,SELECT * FROM)你可能会浪费内存和带宽以存储和接收那些多余的列。
  • 尽可能在源数据库或者目标数据库进行时间日期类型的转换,由于在SSIS实现的话成本过高。
  • SQL Server 2008 Integration Servcies有个新功能Shared Lookup Cache。当用到并行数据管道时(参见下文第8点和第10点),这个功能能够提供高速的共享缓存。
  • 若是SSIS和SQL Server运行在同一台服务器上,建议选择SQL Server Destination而不是OLE DB Destination以提升性能。
  • Commit Size为0的话在堆上进行批量操做是最快的,由于只提交了一个事务。若是不能为0,尽可能提升这个值以减小多批次写入的开销。将数据插入平衡树结构时Commit Size为0则不是个好主意——由于全部新进的行都必须一次性排序以插入目标平衡树——而且若是你的内存有限,颇有可能溢出到硬盘上。将数据插入堆时Batch Size为0是个比较理想的值。对于一个有索引的目标(表),我建议测试一下将Batch Size设在100000到1000000之间。
  • 插入数据时将Commit Size设为小于5000能够避免锁升级。要注意的是在SQL Server 2008如今你能够在对象级别启用/禁用锁升级,不过要灵活调整这个设置。
  • 对堆进行插入每每比汇集索引快。这意味着当目标表发生大量更改的时候你可能会删除并重建索引,你能够验证一下保留索引和删除并重建索引两种方法的插入性能。
  • 采用Partition和分区的SWITCH命令。例如,将数据载入只有单个分区的工做表,重建索引和约束后再将它SWITCH到主(目标)表。
  • 请参考SQL性能团队的另外一个建议用Lookup优化性能

5.调整网络

一个关键的属性是链接的网络包大小。默认状况下这个值是4096字节。这意味着每4KB数据必须封装为一个新的网络包。正如SqlConnection.PacketSize Property中所述在.Net Framework类库中,增长网络包大小能够提升性能,由于传输大数据集的时候这意味着更少的网络读写操做。

若是你的系统天生就是事务性的,有不少小数据量的读/写,那么减少这个值会提升性能。

既然SSIS主要用于移动大量数据,你可能但愿最小化网络开销。这意味着32767是最快的选项。也能够在服务器层面用sp_configure配置网络包大小,然而你不该该这么作。将网络包配置为32767之外的值,DBA可能有他们的考虑。做为替代方案,你能够在Connection Manager里以下覆盖服务器设置。

 

另外一个网络优化技巧是在操做系统层面采用Network Affinity。在高吞量的状况下,有时你能够经过这个办法提升性能。

单从网络来看,你可能须要与你的网络管理员协做启用Jumbo Frames(巨型帧)以便将帧负载能力从1500字节提升到9000字节。采用这种方法,将极大地减小移动大数据集所需的网络操做。

6.数据类型——没错,回到数据类型!——理性点。

在本文的10点建议中,这多是最显而易见的。然而,这是如此重要因此须要专门做为一点建议。请遵循如下准则:

  • 使数据类型尽量小以节约内存。
  • 切勿执行代价高昂的类型转换——这只会下降性能。匹配源和目标的数据类型并显式指定必要的类型转换。
  • 当你用到money,float,或者decimal类型时留意精度问题。同时,要注意money比decimal更快,并且在精度方面money也比float更让人放心。

7.改变设计

SSIS比较擅长一些事情,而其它事情用别的工具更方便。你必须基于效率和对问题的了解来选择ETL工具。为辅助你的选择,请注意如下几点:

  • 除非必要,不然切勿在SSIS中排序。为了进行排序,SSIS会分配足以容纳整个(须要移动的)数据集大小的内存。请尽可能在数据进入数据流以前就提早排好序。相对于在SSIS中排序,不如用带ORDER BY子句的SQL语句去排序大型数据集——而后将Data Source的输出标记为Sorted(有序)便可。
  • 有些时候用T-SQL操做会比在SSIS中处理数据更快。做为通常性原则,任何基于集合的操做在T-SQL中老是比较快,由于问题能够转化为SQL Server擅长解决的关系代数函数。而且,SQL Server查询优化器对基于集合的操做自动采用了高并行处理和内存管理机制——在SSIS中你须要手工去实现。典型的集合操做包括:
    • 基于集合的UPDATE语句——比逐行处理的OLE DB调用更高效。
    • 像GROUP BY和SUM这样的聚合计算。这用T-SQL计算一般会比SSIS在内存中的计算更快。
  • 分支检测是一种更改已有行而不是刷新整张表的技巧。为实现分支检测,你能够采用更改检测机制,例如SQL Server 2008的Change Data Capture(CDC)功能。若是没法采用这样的功能,你不得不比对源数据与目标数据以实现分支检测。这多是个代价高昂的操做,须要维护特定的索引并计算校验和。一般,刷新整张表会比较快。一个经验是一旦某个表超过10%的行须要更改,那么一般简单地刷新这张表会比实现分支检测更快。

8.分割问题

可伸缩计算的一个原则就是分而治之。这使你能够更容易地处理问题的规模,利用并行处理以更快地解决问题。

对ETL设计来讲,你可能会将源数据分割成大小相同的小数据块。这一点很重要,由于若是你的数据块大小有差别,最后你总得等待某个进程完成。好比说,以下图,当4个进程分别运行在大小相同的数据块,4个进程会同时完成2008年1月份数据的处理并开始处理2008年2月份的数据。但对于大小有差别的分割方式,前面的3个进程将同时完成数据处理而后等待第4个进程,这得花费更多时间。总的运行时间将取决于最大的数据块。

 

为建立相同大小的分区范围,能够考虑用时间区间和/或其它维度(例如地理信息)做为分割机制。若是你的主键是个自增列或者其它自增值,你能够用余函数。若是你没有比较合适的列用于分区,能够为每一行计算一个哈希值而后基于这个哈希值进行分区。

一些关于分区的提示:

  • 在目标表应用分区。这样你能够并行地运行一个包的多个版本,以便将数据插入同一张表的不一样分区。用了分区,SWITH就是你的好朋友。它不只增高并行载入的速度,也使你能够更快地传输数据。请参考SQL Server在线文档使用分区切换高效传输数据
  • 如上文所暗示的,你的包须要接受一个参数以指定它要抽取哪一个分区。这样一来,你能够以不一样的参数同时并行执行同一个包,那么你能够从并行执行中得到更快的速度。
  • 从命令行,你能够用“START”命令屡次执行包。你能够在SQL Server最佳实践找到一个简单的代码示例。

9.最小化日志操做

当你插入数据到SQL Server数据库,尽可能最小化日志操做。当数据插入到完整日志模式的数据库,因为每一行都会先插入日志,日志会快速增加。

所以,设计SSIS包时,考虑如下几点:

  • 尝试以批量模式而不是逐行模式执行数据流。经过批量导入模式,你能够最小化插入日志的操做。这个调整也能够优化其它插入操做的底层磁盘I/O,并最小化日志写入形成的性能瓶颈。
  • 若是你须要执行删除操做,将你的数据构形成能够TRUNCATE的形式而不是DELETE。后者会在日志中为删除的每一行放一条记录。而前者会简单地移除所有数据同时在日志作很小的记录代表TRUNCATE发生过。与通常的观点相对地,TRUNCATE语句能够包含在事务中。
  • 利用SWITCH和分区。若是分区须要被移除,你能够用SWITCH语句(移入一个新分区或者移除最老的分区),这也是最小化日志操做的语句。
  • 使用DML语句的时候要谨慎,若是你将DML语句混在INSERT语句中,没法最小化日志操做。

10.正确地计划与分发

当你的问题被分割成大小可控的数据块以后,你得考虑一下何时以及在哪里抽取这些数据块。这是为了不一个长时间运行的任务影响ETL数据流的总运行时间。

解决执行顺序的一个好办法就是建立一个优先级队列而后执行一个包的多个实例(分别带有不一样的参数)。这个队列甚至能够简单到就是SQL Server的一张表。每一个包都得在控制流包含一个循环模板:

1.  从队列中找出一个要抽取的数据块:

  1. 这意味着这个数据块尚未抽取,而且它依赖的数据块都已经抽取了。
  2. 若是队列没有返回任何项,退出包的执行。

2. 执行这个数据块所需的操做。

3. 在队列中将数据块标记为“已抽取”。

4. 返回循环的起点。

从队列中提取一个数据块并标记为“已抽取”(上面的第一和第三步)能够实现为存储过程。

这个队列扮演了一个控制中心的角色并起到协调的做用,它能够判断执行顺序并确保任意两个包不会工做在相同的数据块上。一旦这个队列就绪,你能够简单地启动多个DTEXEC副本以提升并行度。

点击加入SQL Server精英群SQLServer精英群

点击访问软件技术咨询中心

相关文章
相关标签/搜索