微软BI 之SSIS 系列 - 再谈Lookup 缓存

开篇介绍

关于 Lookup 的缓存其实在之前的一篇文章中已经提到了 微软BI 之SSIS 系列 - Lookup 组件的使用与它的几种缓存模式 - Full Cache, Partial Cache, NO Cache 但是还是可能遗漏的部分内容,因此在这里重新总结并补充一下。这是第一篇,还是从理论的角度来讨论 Lookup 缓存的问题;后面有空还会再写一篇,从后台 SQL 执行的情况来理解 Lookup 的工作过程。

并且关于 Lookup 缓存还有其它比较有意思的话题,比如我的这些帖子,大家都可以关联起来看看:

我们还是从 OLE DB Connection Manager 下的这三种缓存模式来讨论:Full Cache 完全缓存,Partial Cache 部分缓存,NO Cache 不缓存

在下面示例中, FF_SRC_INTERNET_SALES 是文件数据输入源,LKP_SALES_ORDER_NUMBER 是 Lookup 组件。

Full Cache 完全缓存

完全缓存 - Lookup 的默认缓存。

第一步:在这种模式下,在数据流预执行 Pre-Execute 即执行之前就会将查询发送给数据库服务器并将数据查询后返回,并缓存到 SSIS 运行时内存中。之后,右侧数据库中的数据即 Lookup 中配置的视图或表 【T032_SALESORDER】中的数据发生任何变化跟缓存中的数据是没有任何关系的。

第二步:数据流此时才开始执行,缓存中已经含有数据了,这时来自于 FF_SRC_INTERNET_SALES中数据就会通过之前配置好的匹配规则使用列 SalesOrderNumber 和 列SalesOrderLineNumber 的值到缓存中查找有没有匹配的 SalesOrderNumber 和 SalesOrderLineNumber。

第三步:如果在缓存中匹配到了相应的数据,那么上图中 Available Input Column (即文件源中的列) 和 Available Lookup Column (即缓存中的列 - 视图或表 T032_SALESORDER 中的列) 中被打勾的列 (此示例中无勾选上的选项) 共同形成一个输出列组:Available Input Column + Available Lookup Column 选中的列向下输出,输出的名称默认叫做  Lookup Match Output。

第四步:如果在缓存中找不到相应的数据,那么根据不匹配的规则(这里选择的是 Redirect rows to no match output)将 Available Input Columns 中的数据作为不匹配数据往下输出,输出名称叫做 Lookup No Match Output。注意:错误数据的内容就不是 Available Input Columns 中的数据了。

那么上面的几个步骤就是在 OLE DB Connection 下的 Lookup 的完全缓存模式与查找输出的流程。

主要特点

  • 数据流启动之前(甚至更早,在包执行之前)完成数据查询与缓存动作,查询结果集缓存起来。
  • 消耗内存大,增加了数据流启动的时间。
  • 在数据流执行的时候非常快,源数据直接和缓存数据做比较,不用再次查询数据库。
  • 缓存数据源中的数据变更将也不再影响到缓存中的数据。
  • 如果缓存的数据容量超过了内存的大小,那么会出现内存不足报错 Out Of Memory,因为缓存不会主动把数据写入到磁盘上。

何时使用完全缓存 Full Cache

  • 引用数据集中的数据量无论大小,只要不超过内存大小,特别当数据源的数据和引用数据集匹配程度高的时候,一次缓存可以反复使用。
  • 数据库服务器不在本地,或者数据库服务器压力很大,为了减少反复的连接反复的查询对数据库服务器造成更大的压力。

使用完全缓存 Full Cache 中的关键点

  • 数据全部缓存在内存中,如果内存不够并不会将超出部分的数据缓存到磁盘上,而是直接报错 - Run out of memory。
  • 由于数据集缓存在内存中,所以在使用 Lookup 的时候不应该直接使用表对象,而应该通过写 SELECT 语句来减少不必要的列输出并且可以加上 WHERE 条件来限定一下数据集的大小,简而言之缓存的数据应该只包含有用的数据。
  • 数据一旦缓存,那么在数据流执行过程中就不会再去检测之前源数据是否发生改变或者更新等等,除非数据流重新启动执行。

Partial Cache 部分缓存

第一步:部分缓存模式下,在数据流执行之初 Lookup 缓存还是空的。当 Lookup 组件开始读入 FF_SRC_INTERNET_SALES 数据源中的列时,此时因为需要对比才开始检查缓存中是否有匹配的值。

第二步:缓存中如果有,则直接可以作为匹配输出向下输出了。

第三步:缓存中如果没有,这时就会发送查询到数据库中进行查询(查询语句可以配置参数)。如果在数据库中查找了就会将这个已查到的内容缓存在匹配缓存区中,以供下次使用,这次还是匹配输出。

第四步:如果缓存中没有,查询数据库后也没有,根据配置可以将此条在缓存中没有在数据库中也没有的数据按照配置放在不匹配缓存区以供下次做不匹配检查。因为都查找不到,因此这次是不匹配输出。

特点

  • 数据流启动之前,缓存为空,数据流启动时间要比完全缓存的情况下要快。
  • Lookup 的时候会慢,因为总要检查缓存,如果有的话就直接用,如果没有的话就需要查询数据库,每次查询都是一次开销。如果数据量比较大的话,这种频繁的查询对数据库服务器压力会比较大。所以从 FF_SRC_INTERNET_SALES 到 LKP_SALES_ORDER_NUMBER  数据流的传递明显要慢,传递一批等一会,因为此时 LKP_SALES_ORDER_NUMBER 需要到数据库中去查数据。即时当 FF_SRC_INTERNET_SALES 数据抽取完毕之后,下面的三个控件还要执行半天。
  • 可以在 Advanced Options 中设置最大缓存(32位模式和64位模式两种选择),一旦缓存中的实际数据大小超过这个最大值的话,就会自动清理那些对比中较少使用的行以便为新的数据腾出空间。
  • 可以在 Advanced Options 中设置不匹配缓存区所占缓存区的比例,这样在一条源数据在匹配缓存中查询不到,在数据库中也查询不到的情形下,这条数据的关键比较列就会存入不匹配缓存区。下次来的数据如果还在匹配缓存区中找不到的时候,就会先看看不匹配缓存区中是否存在,这样就会减少对数据库的反复查询的几率。如果数据源中的数据与 Lookup 引用集中的数据匹配率很低,可以适当的提高不匹配缓存区的比例。
  • 当某次查询数据库时发生 Lookup 引用数据表中的数据发生了变化,此时不匹配缓存区将会默认禁用。应该当 Lookup 引用数据表数据相对稳定没有再发生变化的时候,不匹配缓存区将会重新分配。

什么时候使用 Partial Cache 部分缓存

  • 数据源中的数据比较少的时候,这样查询的次数就小。
  • 引用数据集中的数据很大,内存无法支持的时候。
  • 引用数据集源表的数据发生变化,需要在查询匹配过程中也能知晓的情况下。
  • 当需要使用参数化查询来限制引用集的大小的时候可以考虑使用 Partial Cache。

使用 Partial Cache 部分缓存要注意的地方

  • 注意缓存区的大小分配尽量足够大,上图中 25MB 实在大小。
  • 合理的使用不匹配缓存区,不匹配程度高的时候提高不匹配缓存区的占比。

No Cache 不缓存

无缓存模式下,每次匹配查询都会去数据库查一次。这种缓存模式下,数据量不大并且内存比较紧张的情况下才会使用,当然它对内存的消耗也相对最小,但效率也最低。

总结

就我个人而言,目前对 Lookup 的使用配置情况基本上都默认选择 Full Cache 模式,因为现在内存的支持完全不是什么大问题。一个 10 W 的输入 Lookup 一个 1 W 多的引用集基本上在完全缓存模式下几秒就可以解决掉;如果换成 Partial Cache 或者 No Cache 至少超过 60秒或者更多。所以,在实际开发中基本上可以保持默认选择 Full Cache 就可以达到一个最优效率的使用,除非内存紧张才会在缓存分配比率上做文章。

跟这篇文章相关的文章还有

更多 BI 文章请参看 BI 系列随笔列表 (SSIS, SSRS, SSAS, MDX, SQL Server)  如果觉得这篇文章看了对您有帮助,请帮助推荐,以方便他人在 BIWORK 博客推荐栏中快速看到这些文章。

时间: 2024-10-12 13:14:16

微软BI 之SSIS 系列 - 再谈Lookup 缓存的相关文章

微软BI 之SSIS 系列 - Lookup 中的字符串比较大小写处理 Case Sensitive or Insensitive

前几天碰到这样的一个问题,在 Lookup 中如何设置大小写不敏感比较,即如何在 Lookup 中的字符串比较时不区分大小写? 实际上就这个问题已经有很多人提给微软了,但是得到的结果就是 Closed and Won’t fix. 说白了,这个就是 By Design,包括到现在的 2012 也没有这个配置选项. https://connect.microsoft.com/SQLServer/feedback/details/339069/ssis-case-sensitive-data-flo

微软BI 之SSIS 系列 - 对于平面文件中 NULL 值处理过程中容易极易混淆的几个细节

最近有人问我 OLE DB Destination 中的 Keep Nulls 如何控制 NULL 值的显示,为什么选中了 Keep Nulls 但是数据库中没有 NULL 值? 为什么在 Flat File Source 中勾选上了 Retain null values from the source as null values in the data flow 但是为什么目标表上显示的是一个当前日期,而不是 NULL 值等等,单开此文来解释这些非常容易混淆的概念. 在比较纯粹的 ETL 项

微软BI 之SSIS 系列 - 使用 Script Component Destination 和 ADO.NET 解析不规则文件并插入数据

开篇介绍 这一篇文章是 微软BI 之SSIS 系列 - 带有 Header 和 Trailer 的不规则的平面文件输出处理技巧 的续篇,在上篇文章中介绍到了对于这种不规则文件输出的处理方式.比如下图中的这种不规则文件,第一行,第二行 Header 部分,第三行的内容 Content 部分,最后一行的 Trailer 部分. 在前几个课程 微软BI SSIS 2012 ETL 控件与案例精讲 第43,44,45,46 课中,我分别讲解了如何使用 .Script Component Source 解

微软BI 之SSIS 系列 - 带有 Header 和 Trailer 的不规则的平面文件输出处理技巧

案例背景与需求介绍 之前做过一个美国的医疗保险的项目,保险提供商有大量的文件需要发送给比如像银行,医疗协会,第三方服务商等.比如像与银行交互的 ACH 文件,传送给协会的 ACH Credit 等文件.这些文件格式在美国都是开放的,通用的,可以直接到相关网站下载.也就是说像银行,协会等他们接受这种固定格式的文件,读取数据,读取公司编号进行业务来往或者记录.我当时就是直接在网上搜索到一个 PDF 格式的文件说明,大概有10来页,就是告诉你这个格式是如何定义,应该如何来处理的. 那么这种文件并非像我

微软BI 之SSIS 系列 - 在 SSIS 中导入 ACCESS 数据库中的数据

开篇介绍 来自 天善学院 一个学员的问题,如何在 SSIS 中导入 ACCESS 数据表中的数据. 在 SSIS 中导入 ACCESS 数据库数据 ACCESS 实际上是一个轻量级的桌面数据库,直接使用文件形式存储.在国内大量使用 ACCESS 作为 BI 数据源并不多,但是在国外特别是美国使用的还比较多,因为他们的 IT 基础起步比较早.在我的第一个美国的医疗保险项目中,就遇到过大量的 ACCESS 数据源,前后总共有 500 多个 ACCESS 表.而现在从国外一些朋友反馈的情况仍然还有在使

微软BI 之SSIS 系列 - MVP 们也不解的 Scrip Task 脚本任务中的一个 Bug

开篇介绍 前些天自己在整理 SSIS 2012 资料的时候发现了一个功能设计上的疑似Bug,在 Script Task 中是可以给只读列表中的变量赋值.我记得以前在 2008 的版本中为了弄明白这个配置,还特意测试过这个细节,获取错误并理解了这个功能.但是现在回去再次测试 2008 的版本时,发现这个功能在 2008 中其实也是错误的,把我印象中的测试结果完全给推翻了,所以到现在已经搞不清楚我当时到底是如果得出这个错误的. 疑似功能 Bug 描述 在 SSIS 包中定义了用户自定义变量 - PV

微软BI 之SSIS 系列 - 使用 Script Task 访问非 Windows 验证下的 SMTP 服务器发送邮件

开篇介绍 大多数情况下我们的 SSIS 包都会配置在 SQL Agent Job 中周期性的按计划执行,比如每天晚上调用 SSIS 包刷新数据,处理 Cube 等.一旦 SSIS 包中出现任何异常,报错,那么配置在 SQL Agent Job 中的通知,邮件提醒就会把这些错误信息发邮件到指定的用户或者系统维护者,这样就起到了一个错误监控的作用. 但是在有的情况下,有一些自定义的 SSIS 调度框架的计划调度都不是通过 SQL Agent Job 配置来完成的.比如我以前在一个小项目中设计过一个

微软BI 之SSIS 系列 - Execute SQL Task 中的 Single Row 与 Full Result Set 的处理技巧

开篇介绍 Execute SQL Task 这个控件在微软BI ETL 项目中使用的频率还是非常高的,也是大部分入门 SSIS 初学者最早接触到的几个控制流控件. 我们通常使用 Execute SQL Task 的场景包含但不止于以下几类: 在从源端加载数据到 Staging 表之前使用 Execute SQL Task 执行一些 Truncate 操作. 执行一些 Log 的插入,更新操作. ETL 过程中的 Merge 语句操作. XML 的输出处理. 关于如何使用 Execute SQL

微软BI 之SSIS 系列 - 使用 SQL Profilling Task (数据探测) 检测数据源数据

开篇介绍 SQL Profilling Task 可能我们很多人都没有在 SSIS 中真正使用过,所以对于这个控件的用法可能也不太了解.那我们换一个讲法,假设我们有这样的一个需求 - 需要对数据库表中的一些数据做一些数据分析,比如统计一下数据表中各列中实际数据的长度,各长度区间范围:比如统计一下各数据列中非空字段的比例,表的行数,重复字段等等.那么如果不是专门做过这种数据源数据分析的话,可能不知道用什么方式能够非常快的得到这些信息.写 SQL 语句?我想这个过程也是非常耗费时间和精力的. 实际上