我有一个SQL服务器,它通过合并复制到运行SQL CE的800个移动客户端进行设置。
服务器有足够的资源,进出公司的线路绰绰有余,客户端和服务器之间的复制通常都很好,但我们遇到了一个我无法追踪的间歇性错误。
昨天我们需要在一个主表中插入550条记录,唯一存在的触发器是标准的合并复制表。
这个插件花了14个小时,因为它不断地与试图同步的移动设备陷入僵局。
有没有人对如何避免插入锁定以及如何加快整个过程有任何建议?
------更新-----
继一些评论后,我在一个插页上运行了一个分析器,我看到了很多这类东西
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)
对于许多我不打算插入的表......这可能是一个线索吗?
答案 0 :(得分:8)
我们最近在我们的系统中遇到了与您的相似的行为。原因是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
答案 1 :(得分:0)
到目前为止,最终索引只有帮助,看起来合并复制在这个系统上设置得不是很好。
然而,在没有触发触发器的情况下使用批量插入然后使用sp_addtabletocontents解决了我们的问题。
作为附注,我们必须进行基本更新
更新表集Column1 = Column1
在我们执行批量插入之后,以便合并复制通知其他链接表它已更改,否则并非所有数据都正确传播。