Recently in a merge replication scenario with SQL 2008 RTM and SQL Compact cleints we experienced a massive slowdown in server operations during sync. Digging into the process we found that the sp_MSsetupbelongs procedure calls are lengthy. Further profiling and tests revealed that the longest step is a simple looking insert statement into a temp table:
insert into #notbelong (tablenick, rowguid, flag) select distinct 4038005 , [article1].rowguidcol, -1 from [dbo].[article1] [article1], MSmerge_bi_98DAC279CFFC4D03B886B646B914017A_v_3FE29C0B84BE4927B7EAAB819F09F5D5 [article2], #notbelong nb where (article2.fej= article1.id) and nb.tablenick = 4038006 and [article2].rg = nb.rowguid
This insert is inside an expand procedure MSmerge_expand_13, and in the reproduced environment takes some 3 minutes to complete. The select itself produces two rows in zero seconds, the #notbelong table contains 24640 rows before the insert. The #notbelong table and its indices are created by sp_MSsetupbelongs. If in MSmerge_expand_13 we drop the index on #notbelong the insert is fast. Replacing the above insert with one that uses a cursor on the select is also efficient even with the index on. Using another temp table accepting all rows from the select without distinct and than inserting distinct rows from this table is also efficient.
How on earth can such an insert be that slow?