2012-10-22 9 views
10

Ho un server SQL che viene configurato con la replica di tipo merge su 800 client mobili che eseguono SQL CE.Gli inserimenti nel database Merge Replication sono follemente lenti

Il server dispone di risorse sufficienti e le linee interne e esterne dell'azienda sono più che adeguate, la replica tra i client e il server è generalmente buona, ma riceviamo un errore intermittente che non riesco a rintracciare.

Ieri abbiamo dovuto inserire 550 record in una delle nostre tabelle principali, gli unici trigger esistenti sono quelli di replica standard.

Questo inserto ha impiegato 14 ore a causa del suo continuo blocco con dispositivi mobili che tentano di sincronizzarsi.

Qualcuno ha qualche consiglio su come evitare i blocchi sugli inserti e su come accelerare l'intero processo?

------ Aggiornamento -----

A seguito di alcuni commenti che ho incontrato un profiler nel corso di un unico inserto e sto vedendo un sacco di questo genere di cose

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) 

Per molti tavoli che non ho intenzione di inserire in ... potrebbe essere un indizio?

+0

1. Quali sono i livelli di isolamento utilizzati da insert e syncs? Di solito l'inserimento non dovrebbe essere un problema. 2. Quanti indici hai? 3. Avete indici che non sono incrementali e causeranno l'inserimento di record nel mezzo della struttura ad albero invece della fine? 4. Hai un indice cluster? – Farfarak

+0

1. Non sono sicuro sui livelli di isolamento .. è solo un'istruzione di inserimento standard - 2. Stiamo inserendo nella tabella A che ha 1 indice standard .. tuttavia i trigger di replica di unione lo incollano in molte altre tabelle - 3. Non sul tavolo stiamo inserendo in - 4. No –

+0

1. Avete richieste che vengono chiamate durante la replica potrebbe essere che il processo di replica blocchi l'intera tabella nel vostro caso (non avete indice cluster) 2. C'è una chiave univoca sul tavolo ? – Farfarak

risposta

0

Negli indici finali ha contribuito solo finora, sembra che la replica di tipo merge non sia impostata molto bene su questo sistema.

Tuttavia, l'utilizzo di Inserimento di massa senza inneschi di attivazione e l'utilizzo di sp_addtabletocontents ha risolto il problema.

Come nota a margine che abbiamo dovuto fare un aggiornamento di base

Aggiornamento Table set Colonna1 = Column1

dopo che abbiamo fatto l'inserimento di massa in modo che la replica di unione notificato le altre tabelle collegate che non aveva cambiato il resto tutti i dati si sono propagati correttamente.

8

abbiamo recentemente riscontrato lo stesso comportamento nel nostro sistema, che è abbastanza simile al tuo. Il motivo erano enormi quantità di dati in msmerge_contents e msmsmerge_current_partition_mappings, e abbiamo notato che potrebbe essere un indice mancante osservando il numero di righe lette in SQL Profiler. (49 000 000 legge per un semplice inserimento in uno per le tabelle sembrava un po 'troppo)

risolto 30 minuti fa con l'aggiunta di due indici:

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]) 

Spero che questo ti può aiutare, che ci ha aiutato in basso il tempo di interrogazione da 5 minuti a 10 secondi.

- Un paio di ore più tardi ...

mio collega trovato un altro indice che aumenta ulteriormente le prestazioni da un altro 75%:

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

Identificare indice mancante È possibile utilizzare il seguente script per identificare gli indici mancanti, ordinati con quello previsto per aumentare le prestazioni più in alto (Esistono numerosi script di questo tipo, questo è stato preso in prestito da 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