【问题标题】:Inserts in Merge Replication database are insanely slow合并复制数据库中的插入非常慢
【发布时间】:2012-10-12 04:00:49
【问题描述】:

我有一个 SQL 服务器,它设置了合并复制到 800 个运行 SQL CE 的移动客户端。

服务器有足够的资源,进出公司的线路绰绰有余,客户端和服务器之间的复制通常很好,但我们遇到了一个我无法追踪的间歇性错误。

昨天我们需要将 550 条记录插入到我们的一个主表中,唯一存在的触发器是标准的合并复制触发器。

此插入需要 14 小时,因为它不断与尝试同步的移动设备陷入僵局。

对于如何避免插入锁定以及如何加快整个过程,有人有什么建议吗?

----- 更新-----

从一些 cmets 开始,我在单个插入上运行了分析器,我看到了很多这样的事情

insert into dbo.MSmerge_current_partition_mappings with (rowlock) (publication_number, tablenick, rowguid, partition_id)
            select distinct 1, mc.tablenick, mc.rowguid, v.partition_id
            from dbo.MSmerge_contents mc with (rowlock) 
            JOIN dbo.[MSmerge_JEMProjectME_PromotionResource_PARTITION_VIEW] v with (rowlock) 
            ON mc.tablenick = 286358001
            and mc.rowguid = v.[rowguid]
            and mc.marker = @child_marker 
            and v.partition_id in (select partition_id from dbo.MSmerge_current_partition_mappings cpm with (rowlock) JOIN
                dbo.MSmerge_contents mc2 with (rowlock)
                ON cpm.rowguid = mc2.rowguid
                and mc2.marker = @marker)
            where not exists (select * from MSmerge_current_partition_mappings with (readcommitted, rowlock, readpast) where 
                publication_number = 1 and 
                tablenick = 286358001 and
                rowguid = v.[rowguid] and
                partition_id = v.partition_id)

对于许多我不打算插入的表...这可能是一个线索吗?

【问题讨论】:

  • 1. insert 和 syncs 使用的隔离级别是什么?通常插入应该不是问题。 2. 你有多少个索引? 3. 你有不是增量的索引,会导致记录被插入树结构的中间而不是末尾? 4. 你有聚集索引吗?
  • 1.不确定隔离级别..这只是一个标准的插入语句 - 2. 我们正在插入具有 1 个标准索引的表 A.. 但是合并复制触发器将其粘贴到许多其他表中 - 3. 不在我们插入的表上进入 - 4. 没有
  • 1.您是否有在复制期间被调用的查询,可能是复制过程在您的案例堆中阻塞了整个表(您没有聚集索引) 2. 表上是否有唯一键?
  • 是的,进程和其他复制请求一直都在进来。我们有大约 800 个移动客户端,每个客户端每天复制大约 10 次,因此它们经常相互重叠,并且工作......只是重新检查。表上没有唯一键
  • 我建议在表上设置聚集索引,它是顺序的,并确保复制基于它进行选择,并且复制和插入不应该在 SERIALIZABLE 事务隔离级别上运行,这样你会没有 RangeS-S 或 RangeI-N 锁,如果您有死锁图,这很可能是死锁原因。

标签: sql sql-server-2008 merge-replication


【解决方案1】:

我们最近在我们的系统中遇到了与您的非常相似的相同行为。原因是 msmerge_contents 和 msmsmerge_current_partition_mappings 中有大量数据,通过查看 SQL Profiler 中读取的行数,我们注意到它可能是缺失的索引。 (49 000 000 次对表格的简单插入读取似乎有点多)

30 分钟前通过添加两个索引解决:

CREATE NONCLUSTERED INDEX [IX_MSmerge_current_partition_mappings_PERF1] ON [dbo].[MSmerge_current_partition_mappings] 
(
    [partition_id] ASC
)
INCLUDE ( [rowguid]) 


CREATE NONCLUSTERED INDEX [IX_msmerge_contents_PERF1] ON [dbo].[MSmerge_contents] 
(
    [marker] ASC
)
INCLUDE ( [rowguid])

希望对您有所帮助,它帮助我们将查询时间从 5 分钟缩短到 10 秒。

-- 几个小时后……

我的同事发现了另一个指数,进一步提高了 75% 的性能:

CREATE NONCLUSTERED INDEX [IX_MSmerge_current_partition_mappings_PERF2] ON [dbo].[MSmerge_current_partition_mappings] 
(
    [rowguid] ASC,
    [partition_id] ASC
)

识别缺失的索引 您可以使用以下脚本来识别缺失的索引,将期望提高性能的那个排在最前面(这样的脚本很多,这个是从http://www.sherbaz.com/category/sqlserver/借来的)

SELECT  sys.objects.name
, (avg_total_user_cost * avg_user_impact) * (user_seeks + user_scans) AS Impact
,  'CREATE NONCLUSTERED INDEX ix_IndexName ON ' + sys.objects.name COLLATE DATABASE_DEFAULT + ' ( ' + IsNull(mid.equality_columns, '') + CASE WHEN mid.inequality_columns IS NULL 
                THEN ''  
    ELSE CASE WHEN mid.equality_columns IS NULL 
                    THEN ''  
        ELSE ',' END + mid.inequality_columns END + ' ) ' + CASE WHEN mid.included_columns IS NULL 
                THEN ''  
    ELSE 'INCLUDE (' + mid.included_columns + ')' END + ';' AS CreateIndexStatement
, mid.equality_columns
, mid.inequality_columns
, mid.included_columns 
    FROM sys.dm_db_missing_index_group_stats AS migs 
            INNER JOIN sys.dm_db_missing_index_groups AS mig ON migs.group_handle = mig.index_group_handle 
            INNER JOIN sys.dm_db_missing_index_details AS mid ON mig.index_handle = mid.index_handle AND mid.database_id = DB_ID() 
            INNER JOIN sys.objects WITH (nolock) ON mid.OBJECT_ID = sys.objects.OBJECT_ID 
    WHERE     (migs.group_handle IN 
        ( 
        SELECT     TOP (500) group_handle 
            FROM          sys.dm_db_missing_index_group_stats WITH (nolock) 
            ORDER BY (avg_total_user_cost * avg_user_impact) * (user_seeks + user_scans) DESC))  
        AND OBJECTPROPERTY(sys.objects.OBJECT_ID, 'isusertable')=1 
    ORDER BY 2 DESC , 3 DESC

【讨论】:

    【解决方案2】:

    最终索引到目前为止只起到了帮助,看起来合并复制在这个系统上设置得不是很好。

    但是使用 Bulk Insert 而不触发触发器然后使用 sp_addtabletocontents 解决了我们的问题。

    附带说明,我们必须进行基本更新

    更新表集Column1 = Column1

    在我们进行批量插入之后,合并复制会通知其他链接表它已更改,否则并非所有数据都正确传播。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-11
      • 1970-01-01
      • 2020-04-02
      • 2017-12-14
      • 1970-01-01
      相关资源
      最近更新 更多