SSIS技巧--优化数据流缓存

问题

我们经常遇到一种情况,在SSMS中运行很慢的一个查询,当把查询转化成从源到目的数据库的SSIS数据流以后,需要花费几倍的时间!源和数据源都没有任何软硬件瓶颈,并且没有大量的格式转换。之前看了很多关于这种情况的优化方案,例如扩大缓存大小等。虽然也能快一点,但是仍然远远比直接在SSMS中查询的速度满的多。究竟是什么原因导致的呢?

解决

首先这个数据流性能是有很多因素决定的,例如源数据的速度、目标库的写入速度、数据转换和路径数量的使用等等。但是,如果只是一个很简单的数据流,那么提高缓存的容量即可改善性能。例如,如果缓存设的更大,那么数据流一次转换更多的数据行,所以性能可以提升。当然很多其他情况就不是这么容易优化了。并且缓存过大时一旦源读取填充缓存时间过长导致了目标库闲置一直处于等待状态直到缓存完成。在这个技巧中,将会介绍如何解决这种问题。

测试场景

首先创建一个百万数据的源表。表结构是一个典型的name-value 键值对表,便于阐述我们的问题。其中value 列设为5000char。如下:

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N‘[dbo].[NameValuePairs]‘) AND [type] IN (N‘U‘))
 DROP TABLE [dbo].[NameValuePairs];
GO

IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID(N‘[dbo].[NameValuePairs]‘) AND [type] IN (N‘U‘))
BEGIN
 CREATE TABLE [dbo].[NameValuePairs]
  ([ID] [int] IDENTITY(1,1) NOT NULL
  ,[Type] [varchar](100) NOT NULL
  ,[Value] [varchar](5000) NULL
  PRIMARY KEY CLUSTERED ([ID] ASC));
END
GO

  

使用AdventureWorksDW2012 样板数据,你可以搜索下载。表中有各种用户信息:names, gender, addresses, birth dates, email addresses 和phone numbers。如下:

INSERT INTO [dbo].[NameValuePairs]([Type],[Value])
SELECT
 [Type] = ‘Customer Name‘
 ,[Value] = [FirstName] + ‘ ‘ + [LastName]
FROM [AdventureWorksDW2012].[dbo].[DimCustomer]

UNION ALL

SELECT
 [Type] = ‘BirthDate‘
 ,[Value] = CONVERT(CHAR(8),[BirthDate],112)
FROM [AdventureWorksDW2012].[dbo].[DimCustomer]

UNION ALL

SELECT
 [Type] = ‘Gender‘
 ,[Value] = [Gender]
FROM [AdventureWorksDW2012].[dbo].[DimCustomer]

UNION ALL

SELECT
 [Type] = ‘Email Address‘
 ,[Value] = [EmailAddress]
FROM [AdventureWorksDW2012].[dbo].[DimCustomer]

UNION ALL

SELECT
 [Type] = ‘Address‘
 ,[Value] = [AddressLine1]
FROM [AdventureWorksDW2012].[dbo].[DimCustomer]

UNION ALL

SELECT
 [Type] = ‘Phone Number‘
 ,[Value] = [Phone]
FROM [AdventureWorksDW2012].[dbo].[DimCustomer];
GO 500

  

 
当然也可以自己写一个循环脚本插入数据。DimCustomer 维度表中有18000行数据,通过不同的结果集能返回110,000行数据 。注意这个语句INSERT …SELECT … ,最后有个GO,这不是官方的,但是也是可以用的,后面紧跟的数字表示批处理执行的次数。本例中就是500次。意味着5,500,000行数据被插入,大概有2.3gb。

比如我们可查询邮箱地址:

SELECT [Customer Email] = [Value]
FROM [dbo].[NameValuePairs]
WHERE [Type] = ‘Email Address‘;

  

查询会返回9,242,000 行数据用33秒左右。这个是我们包的最快运行的时间理论上。那么包能不能运行的更快呢?SSIS中将邮件地址转换成邮箱维度表,该列在新表中只有50个字符的宽度,但是在源表中的该列却是5000个字符。但是我们知道在本例中这个邮箱地址不会超过50个字符。

CREATE TABLE dbo.DimEmail
 ([SK_Email] INT IDENTITY(1,1) NOT NULL
 ,[Email Address] VARCHAR(50) NOT NULL
 ,[InsertDate] DATE NOT NULL);

  

SSIS包

生成包是相对简单的,整个控制流由4分任务组成:

  • 第一个任务是记录包开始的日志。
  • 第二个任务是清空目标表。
  • 第三个任务是数据流任务,下面详细介绍。
  • 最后日志记录任务结束。

数据流本身也是很简单:使用前面提到查询读取数据源,然后将加入了审核列和目标表的派生列将结果集写入邮箱维度表。

目标数据库展示了一个截断警告,因为我们试图将超过目标表字段长度的数据插入进来。

初始性能

为了限制外部影响,目标数据库的日志和数据文件足够大,不会影响整个事务。在开发环境下,整个包运行了大约40秒。这是要比直接查询慢的!写入操作是可以被优化的。下面看一下如何优化行数据的插入…

优化数据流

之前提到的最佳实践之一就是扩大缓冲区,具体操作就是修改数据流属性里面的DefaultBufferMaxRows(默认缓存最大行数)DefaultBufferSize(默认缓存大小)。SSIS引擎就是使用这个属性来估计在管道中传送数据的缓存大小。更大的缓存意味着更多行可以被同时处理。

当设定最大值行数为30000并且默认缓存为20M的时候,执行包花费了30秒,这也仅仅比之前源查询快了一点。所以还应该有空间去优化。

在源组件端,估计行的大小是取决于查询返回所有列中的最大列。这也是性能问题的所在:我们建立的键值对表,最大列我5000字符,SSIS引擎将会认为这个列一定包含5000个字符,及时实际上小于50个字符。5000个非Unicode字符等于5000个字节或者5kb。默认的缓存大小事10MB,因此意味着一次仅仅能存储2000行数据,15分之一。这也意味着我们我们并没有最优化的使用缓存。

那么我们只需要调整源数据查询映射的实际数据长度,就能够实现潜在性能的提升。如下:

SELECT [Customer Email] = CONVERT(VARCHAR(50),[Value])
FROM [dbo].[NameValuePairs]
WHERE [Type] = ‘Email Address‘;

  

既然我们已经知道该列最大的是50个字符,改成这样以后一次性能多放入一百倍的数据。当包运行时数据流执行仅仅用了12秒!

我们可以看一下三次不同的包的执行比较(默认配置--扩大缓存--扩大缓存并减小列宽),分别在SSIS catalog 中运行20次在,曲线图如下:

不用多说大家都知道这三种性能如何了。

总结

本篇只是针对数据流进行了优化,并不涉及SQL本身的优化,这里偏重BI一点。通过关注返回源数据的列宽,极大的提高了性能,除此之更小的列性能更好。一次性缓存的行也越多。通过扩大缓存也进一步能提升性能

时间: 2024-08-04 16:34:58

SSIS技巧--优化数据流缓存的相关文章

40个技巧优化您的PHP代码

本文转载 自 PHP技术交流圈 1.如果一个方法能被静态,那就声明他为静态的,速度可提高1/4; 2.echo的效率高于print,因为echo没有返回值,print返回一个整型; 3.在循环之前设置循环的最大次数,而非在在循环中; 4.销毁变量去释放内存,特别是大的数组; 5.避免使用像__get, __set, __autoload等魔术方法; 6.requiere_once()比较耗资源; 7.在includes和requires中使用绝对路径,这样在分析路径花的时间更少; 8.如果你需要

代码示例:一些简单技巧优化JavaScript编译器工作详解,让你写出高性能运行的更快JavaScript代码

告诉你一些简单的技巧来优化JavaScript编译器工作,从而让你的JavaScript代码运行的更快.尤其是在你游戏中发现帧率下降或是当垃圾回收器有大量的工作要完成的时候. 单一同态: 当你定义了一个两个参数的函数,编译器会接受你的定义,如果函数参数的类型.个数或者返回值的类型改变编译器的工作会变得艰难.通常情况下,单一同态的数据结构和个数相同的参数会让你的程序会更好的工作. function example(a, b) { // 期望a,b都为数值类型 console.log(++a * +

10个技巧优化PHP程序Laravel 5框架

性能一直是 Laravel 框架为人诟病的一个点,所以调优 Laravel 程序算是一个必学的技能. 接下来分享一些开发的最佳实践www.itxdl.cn,还有调优技巧,大家有别的建议也欢迎留言讨论. 这里是简单的列表: 配置信息缓存 artisan config:cache 路由缓存 artisan route:cache 类映射加载优化 artisan optimize 自动加载优化 composer dumpautoload 使用 Memcached 来存储会话 config/sessio

第二节 MyBatis的技巧优化

MyBatis的技巧优化 2016年3月2日 星期三 09:13 ?配置日志文件 ?练习 作业: 请分别查询 姓为林的数据  LIKE 3种 Select * from sys_user where user_name like '林%' 关于结果集合多个参数传递数据 特殊字符的处理 核心配置文件,加载jdbc.properties的属性文件 封装工具类

ListView优化-ViewHolder缓存

安卓开发中ListView控件是一个使用频率相当的高级控件,通常用于展示一系列相似度极高的数据,当数据量极大或布局相当复杂时,ListView的性能优化就显得非常重要.所以在开发中不但功能上要满足,而且在性能上也不能马虎.        使用ListView是一个标准的适配器设计模式,ListView把数据.XML布局和Adapter有极地结合在一起完成一系列的展示功能.在ListView的数据展示中,每次滑动ListView都会触发getView()方法的调用,并且XML定义的布局是在也是在适

Mysql性能优化之缓存参数优化

数据库属于 IO 密集型的应用程序,其主要职责就是数据的管理及存储工作.而我们知道,从内存中读取一个数据库的时间是微秒级别,而从一块普通硬盘上读取一个IO是在毫秒级别,二者相差3个数量级.所以,要优化数据库,首先第一步需要优化的就是 IO,尽可能将磁盘IO转化为内存IO.本文先从 MySQL 数据库IO相关参数(缓存参数)的角度来进行IO优化: 一.query_cache_size/query_cache_type (global)    Query cache 作用于整个 MySQL Inst

Apache网页优化之缓存

Apache网页优化之缓存 文章目录 一.Apache的网页缓存 二.网页缓存配置 一.Apache的网页缓存 Apache 的mod_expries 模块会自动生成页面头部信息中的 Express标签和 Cache-Control 标签. 客户端浏览器根据标签决定下次访问是在本地机器的缓存中获取页面,不需要再次向服务器发出请求,从而降低客户端的访问频率和次数,达到减少不必要的流量和增加访问速度的目的. 二.网页缓存配置 1.挂载共享文件,并解压到 /opt/目录下. 安装包优化,转移到http

某大型银行电子渠道报表系统SSIS ETL优化报告

1. 问题分析 1.1 问题场景 在生产环境下,从电子渠道的多个交易系统通过SSIS(SQL Server Integration Services)进行数据服务平台的ETL数据抽取时出现性能问题.在初期使用过程中出现了数据抽取速度过慢和系统资源占用过高的问题,除数据库基础架构建设存在优化可能外,SSIS参数未做面向生产环境硬件的优化也是一个重要原因,导致无法正常发挥SSIS真正性能. 1.2 原因分析 SSIS采用VS2005集成的开发环境,对数据采集的过程可进行可视化的定制开发,对数据量小的

十大技巧优化Android App性能

无论锤子还是茄子手机的不断冒出,Android系统的手机市场占有率目前来说还是最大的,因此基于Android开发的App数量也是很庞大的.那么,如何能开发出更高性能的Android App?相信是软件开发公司以及广大程序员们头疼的一大难题.今天,就给大家提供几个提高Android App性能的技巧. 高效地利用线程 1.在后台取消一些线程中的动作 我们知道App运行过程中所有的操作都默认在主线程(UI线程)中进行的,这样App的响应速度就会受到影响.会导致程序陷入卡顿.死掉甚至会发生系统错误.