3

背景

我有一个单元测试框架,它为我的单元测试创​​建实体,执行测试,然后自动删除实体。除了在我们的开发环境中删除某些实体需要 15 - 30 秒之外,它一直运行良好。

我最近在 Amazon Cloud 中收到了一个 VM 设置,用于执行一些需要几个发布周期才能完成的长期更改。当我在 VM 上运行单元测试时,我不断收到试图删除实体的 SQL 超时错误。

脚步

我已经完成了这组发现/操作步骤:

  1. 打开跟踪,看到fn_CollectForCascadeWrapper用于处理级联删除的超时正在发生。我的单元测试中只有 6 个实体,它们被删除的方式不需要级联删除。Ran Estimated Execution Plan 并添加了它要求的一些索引。这仍然没有解决超时问题。
  2. 打开 VM 上的资源管理器以查看磁盘访问/内存/CPU。当我尝试删除时,CPU 在 2 秒内达到 20%,然后下降到接近 0。内存没有变化,但资源管理器上的磁盘读取访问变得疯狂,并保持这种状态 7-10 分钟。
  3. 硬编码fn_CollectForCascadeWrapper以返回结果,这意味着我的单元测试中的 6 个实体不需要级联。运行单元测试并再次得到 SQL 超时错误。根据跟踪,实际删除语句超时:
delete from [New_inquiryExtensionBase] where ([New_inquiryId] = '7e250a5f-890e-40ae-9d2d-c55bbd7250cd');
delete from [New_inquiryBase]
OUTPUT DELETED.[New_inquiryId], 10012
into SubscriptionTrackingDeletedObject (ObjectId, ObjectTypeCode)
where ([New_inquiryId] = '7e250a5f-890e-40ae-9d2d-c55bbd7250cd')
  1. 在 SQL Management Studio 中手动运行查询。花了大约 3 分钟完成。表上没有触发器,所以我认为时间一定是由于插入。看了SubscriptionTrackingDeletedObject看表,发现里面有 2100 条记录。删除表中的所有记录,并重新运行我的单元测试。它实际上在正常的 15-30 秒时间范围内进行删除。
  2. 研究并发现了SubscriptionTrackingDeletedObject它的用途,并且异步服务清理了它。注意到异步服务没有在服务器上运行。开启服务,等了10分钟,再次查询表。我的 6 个实体仍然列在那里。查看跟踪日志并看到超时错误:Error cleaning up Principal Object Access Table
  3. 研究了 POA 并SELECT COUNT(*)在 table 上执行了一个,7 分钟后它返回了2.61 亿条记录!研究了如何清理桌子,我发现的唯一东西是角色升级 6(我们目前在 11)。

接下来是什么?

POA 会影响删除吗?或者仅仅是影响删除的异步服务的 POA?插入SubscriptionTrackingDeletedObject真的会导致我的问题吗?

4

1 回答 1

2

我最终打开了 SQL Server Profiling,并运行了我的问题中列出的删除语句。执行需要 3.5 分钟。我原以为它会踢出其他东西,打到 POA 表,但不,它只是删除那些记录。

382604 读取

我再次查看了查询执行计划,发现有很多嵌套循环:

在此处输入图像描述

正在查看包含对它的引用的子表(见右下角插入的树结构中的 13 个小分支?)。所以所有的读取都是在索引本身上执行的,并且要花很长时间才能加载到我的超慢虚拟机上。

我最终对不同的 id 运行相同的查询,它在 2 秒内运行。然后我尝试了我的单元测试,最后它成功完成了。

我猜每次我尝试删除时,都会启动一个事务,然后 CRM 的超时回滚事务,永远不允许加载子实体索引。所以我目前的解决方法是确保在实际执行删除之前将子索引加载到内存中。我将如何做到这一点,我不确定(对每个子实体执行 id 查询?)。

编辑

我们请来了一位来自微软的性能分析师,他们写了一份长达 200 多页的报告。98% 的人表示 POA 表太长。 圣诞节期间,我们最终关闭了 CRM 并运行了一些脚本来清理 POA 表。这非常有帮助。

于 2013-10-04T14:24:57.403 回答