SSIS工程师为您揭秘SQL Server数据流

数据库 SQL Server
本文我们主要介绍了SQL Server数据流的相关知识,包括数据流水线、转存与缓存拷贝、以及线程机制等,希望能够对您有所帮助。

我们在操作SQL Server数据库的过程中,常常会听到“数据流”这个术语,那么到底什么是数据流呢?本文我们就介绍一下数据流的相关知识,本文是转载的一位SSIS工程师的文章,接下来就让我们一起来了解一下这部分内容吧。

数据流一瞥

SSIS的引擎(engine)是内存式(in-memory)的:从源(source)读数据,在内存中执行package,再把结果写到端(destination)。尽量不碰外存是其高性能的原因之一。很多以前使用ETL(Extract-Transform-Load)工具的人需要对此调整观念:那些工具先把数据加载到数据库里再做SQL转换,其实是ELT(Extract-Load-Transform)。Matt讲了个很有趣的案例:有位客户的package以前运行只要几分钟,自从服务器升级到新机器后竟然更慢了,要花一个小时。那个package很简单,只是源到端拷贝,中间没有转换(transform),因此客户很生气。

Matt他们急忙去会诊,才发现这个package的源和端以前就在它所运行的那台机器上,在美国; 后来升级了的机器在中国,源和端都跑到了中国来,而package还是在美国那台机器上运行。结果这个package所做的就是从中国读出若干GB的数据到美国的内存,再拷回中国……Matt说,类似的客户问题其实并不少见。SSIS在设计时(design time)阶段就确定了数据流的元数据(metadata)。它在运行之前就精确知道了运行时的列将有多宽,转换需要多少内存,等等。

数据流水线(pipeline)

当数据流启动时,源就开始把一行行数据填到一个类似桶的缓存(buffer)中。源根本不知道下游是什么。一旦缓存满了,桶就随着流水线流到下游组件(component)上,同时引擎抓一个新的空缓存过来给源。源根本不知道这一切,它只是不断地填桶。有时源填了太多的桶,转换和端都来不及应付了;此时引擎会启动反压(backpressure)机制,让源睡眠。

等到流水线又有空间之后,源被唤醒继续填桶。其实在实现上,源甚至都不知道自己被催眠过(好可怜)……直到所有源数据行都发光了,源才在最后一个缓存上贴个“行集末(End Of Rowset)”的标签,把它发出去,告诉下游组件再没有新数据了。

转换与缓存拷贝

SSIS的高性能有部分归功于它在内存使用上比较聪明。在缓存之间拷贝数据是耗时的,因此引擎会尽量减少缓存拷贝。按照缓存使用的不同,可将众多转换组件分为三类。

第一类是同步(synchronous)转换,它们一般逐行对数据做就地修改,从不拷贝缓存。它们有可能增加新行,比如数据转换(Data Convert)和派生列(Derived Column)转换,而仍然是同步的:引擎事先确定了新列将加在哪里,提前就在缓存里加了空列,只是上游组件看不到这些空列罢了。

异步(asynchronous)转换会动态创建新缓存,包括两小类: 部分阻塞(Partially Blocking)转换,一伺新缓存满了就把它输出,比如联合全体(Union All)组件接受多个输入流,一旦从各输入得到了足够多的行就把它输入到一个新缓存里。由于要拷贝数据,这种转换比同步转换慢;但和全阻塞(Blocking)转换相比就好多了。排序(Sort)、聚集(Aggregate)这些全阻塞转换在接收完所有输入行之前,是不会输出一行的。这是由运算本身的特点决定的:不到看到所有数据,是无法确定哪个是最小值的。

因此,在使用全阻塞转换时要格外审慎,尤其是数据量很大时。一旦内存用完,缓存被置换到硬盘上,性能就完了。要想提高数据流性能,最好设法从package中去除全阻塞转换。

线程机制

要理解数据流,还需要了解其线程机制。流水线在运行时被分成若干执行树(Execution Trees)。每个创建新缓存的组件就是一棵新执行树的起点;因此起点要么是个数据源,要么是个异步转换。下图的数据流中有5棵执行树,如蓝箭头所示。引擎限定了每棵树中最多工作的缓存数(目前定为五个),一旦更多缓存进来,就启动反压。注意到多播(Multicast)和条件分割(Conditional Split)转换都是同步的,它们在分割数据流时并不创建新缓存;引擎只是创建了一些能映射到同一块内存的虚拟缓存。所以即使你多播20次也不会看到内存消耗增多。

SSIS工程师为您揭秘SQL Server数据流 

此图修改自Matt的幻灯片

值得一提的是,数据流线程调度在SQL 2008版本中被改进了:在2005版中,每棵树只分到一个线程执行,其问题是对于图中右边那种较长的树,虽然树里都是一序列同步转换,但每次只能在树中移动一个缓存,执行完它之后才能开始执行下一个缓存。很多人为了打碎较长的执行树,就在中间插入一个单输入的联合全体(Union All)组件,由于它是异步的,就能间接引入另一个线程。

而现在,我们在2008版中改为让每个缓存上都有一个线程在执行,这样一棵树中就可以有多个线程在执行。可能第一个线程先把一个缓存进行了三个转换, 然后第二个线程捡起这个缓存继续向下游转换,同时第一个线程开始捡起下一个缓存。这样就再也不需要上述间接的方法了。

关于SQL Server数据流的相关知识就介绍到这里了,希望本次的介绍能够对您有所收获!

【编辑推荐】

  1. SQL Server数据库DataRelation的应用示例详解
  2. SQL Server 2008 MDX应用之检索集合中的元组
  3. SQL Server 2005/2008中的CTE应用之递归查询
  4. SQL Server 2008数据库学习笔记之MDX查询示例
  5. 浅析SQL Server数据库SSIS导入IIS日志的简单步骤
责任编辑:赵鹏 来源: 博客园转载
相关推荐

2011-04-14 14:43:38

SSISTransformat

2011-04-19 09:18:02

SSIS数据转换

2009-04-13 16:35:25

TSQL查询SQL Server

2019-12-19 14:38:08

Flink SQL数据流Join

2010-09-08 17:25:17

SQL全局变量

2022-03-18 08:57:17

前端数据流选型

2011-12-14 15:57:13

javanio

2009-08-19 10:41:12

Java输入数据流

2016-03-21 13:20:45

中国网

2010-09-13 16:19:47

Sql Server数

2017-11-09 14:12:44

大数据软件工程师算法工程师

2010-09-13 17:38:47

Google的系统工程

2016-11-14 19:01:36

数据流聊天系统web

2010-10-22 13:34:49

SQL Server游

2009-02-12 14:45:17

软件工程师

2011-08-19 14:13:39

SQL Server数导入IIS日志

2021-02-25 11:42:23

大数据数据分析sQL

2019-01-21 15:52:02

前端工程师Flutter代码

2010-11-12 11:07:03

sql server内

2010-09-14 13:22:51

sql server备
点赞
收藏

51CTO技术栈公众号