Active Directory:优化检索组成员的函数性能
这篇是《Active Directory:DirectoryEntry成员列表 <> GroupPrincipal.GetMembers()》的续篇。之前我写了个函数用来批量提取AD组里所有成员的distinguishedName属性,这个函数已经集成到一个全量同步AD用户和组的大型脚本里了——整个脚本跑下来要7到10分钟,还算能接受。但现在卡在后续的SSIS Lookup环节了:用distinguishedName做匹配的时候,速度慢得离谱,其实想想也不意外,毕竟distinguishedName是个长字符串,而且默认情况下SSIS Lookup如果用全缓存模式,对非索引列的匹配效率本来就差。
结合我之前处理这类问题的经验,给你几个可行的优化方向:
给Lookup源表的distinguishedName列加索引
如果你的Lookup源是数据库表,这是最直接有效的优化手段。SSIS的Lookup在全缓存模式下会利用索引快速定位匹配项,能把匹配速度提升好几个量级。执行下面的SQL语句就行:CREATE NONCLUSTERED INDEX IX_DistinguishedName ON YourTargetTableName(distinguishedName)要是源表数据更新频繁,可以考虑加个包含索引,把Lookup需要返回的其他列也包含进去,进一步减少IO开销。
切换Lookup的缓存模式
如果源数据量特别大,全缓存占内存太多导致性能下降,或者数据实时性要求高,可以试试部分缓存模式(只缓存高频匹配的条目)或者无缓存模式(每次匹配实时查询源)。不过要注意,无缓存模式会增加源数据库的压力,得根据你的服务器资源情况权衡。预处理生成distinguishedName的哈希值
长字符串匹配天生效率低,我们可以提前给每个distinguishedName生成固定长度的哈希值(比如SHA256),用哈希值作为Lookup的匹配键。哈希值是短字符串,匹配速度会快很多。这里给你一段C#的示例代码,用来生成哈希:using System.Security.Cryptography; using System.Text; public static string GenerateDnHash(string distinguishedName) { if (string.IsNullOrEmpty(distinguishedName)) return string.Empty; using (var sha256 = SHA256.Create()) { var hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(distinguishedName)); var hashString = new StringBuilder(); foreach (var b in hashBytes) { hashString.Append(b.ToString("x2")); } return hashString.ToString(); } }你可以在AD脚本里把这个哈希值和
distinguishedName一起输出到目标表,Lookup时先用哈希值匹配,匹配上后再验证原distinguishedName(防止极低概率的哈希碰撞),既保证速度又不丢准确性。优化AD脚本的输出格式
如果你的脚本是输出到文本文件再导入SSIS,试试用更高效的格式(比如带明确分隔符的CSV,或者直接写入数据库而不是文本文件),减少SSIS加载数据的时间。另外,确保输出的distinguishedName没有多余的空格或特殊字符,避免匹配时的额外处理开销。
内容的提问来源于stack exchange,提问作者J Weezy

