关键问题
我们遇到的延迟不是将更改从分发服务器应用到订阅服务器(如果我们观察复制监视器,它的延迟通常小于 1 秒),而是提交给发布者数据库的事务到达分发服务器所需的时间.
部分问题是我们有几个过滤器应用于我们最易变的表之一,并且在每次更新/插入/删除时,LogReader.exe 需要根据应用的任何过滤器检查将记录放入哪个发布。
从我们所做的测试来看,似乎每应用一个额外的过滤器都会成倍地增加 LogReader 处理每个事务所花费的时间。
(编辑 23/06/2011:添加了有关过滤器的更多详细信息)
背景
在我们的复制设置中,我们有几个出版物在高度易变的表上有过滤器(2 小时内平均有 150 万笔交易)。在繁忙时期,这可能导致 LogReader 以 20 秒的延迟运行(通常 < 1 秒)
我们已经确定了几个改进领域(减少过滤器数量、减少更新数量、外包处理等),一个潜在的改进领域是改变应用更新的方式。
示例表(以帮助解释)
myTable
----------------
myID int
myGroupID1 int
myGroupID2 int
Suspended bit
FilterFlag1 int
FilterFlag2 int
FilterFlag3 int
为了复制来说明这一点,我们将有 5 个[myTable]的出版物:
Publication Filter
----------- ------
NoFilter1 [all records]*
NoFilter2 [all records]*
Filter1 FilterFlag1 = 1
Filter2 FilterFlag2 = 1
Filter3 FilterFlag1 = 1 AND FilterFlag2 = 1
- 其他表格合并到这些出版物中,这就是为什么具有相同过滤器(无)的同一个表格出现在多个出版物中的原因。
当前更新进程
大多数更新此表的应用程序通过循环遍历其对象集合、将更改应用到该单个对象然后将更改提交到数据库,然后再移动到下一个对象来执行此操作。
从数据库跟踪的角度来看,这意味着当发生更改时我们会得到多达 120 个更新语句
例子
update [myTable] set Suspended = @Suspended
where myID = @pID
建议的更新过程
由于对象集合实际上是基于组 ID 的,一个潜在的改进是进行批量更新(而不是单独更新),然后刷新对象集合。将更新语句的数量减少到 1 或 2(取决于业务场景)。
例子
update [myTable] set Suspended = @Suspended
where myGroupID1 = @groupID1
and myGroupID1 = @groupID2
对 LogReader 的影响?
从应用程序处理的角度来看,进行一次更新对我来说很有意义(应用程序和数据库之间的往返次数更少 = 更快),但是我不确定 LogReader 将如何处理这两种情况,因为它需要处理更新的每条记录交易..
LogReader 在批量更新时会更快还是更慢地处理这些记录?
在日志记录中,这些是写入日志的单独语句。然后,日志阅读器将对这些进行批处理,并将它们作为针对数据库的单个事务运行。
如果您的数据库使用存储过程,您可以复制存储过程,这将允许复制存储过程调用而不是实际的数据更新。