2011-04-26 15 views
9

Ok, voy a hacer mi mejor esfuerzo para describir esto. Tengo un SP que pasa en XML y actualizaciones e inserta otra tabla. Esto estaba funcionando ayer. Todo lo que cambié hoy fue cargar la tabla temporal con OPENXML vs xml.nodes. Incluso lo cambié y sigo teniendo este problema interesante. Tengo una actualización e inserto en la misma transacción. La actualización funciona y luego se bloquea, no hay error, no hay nada ... 9 minutos. Normalmente toma 10 segundos. No hay procesos de bloqueo de acuerdo con master.sys.sysprocesses. Lo curioso es que la Selección del inserto no devuelve filas, ya que ya están en la base de datos. La actualización actualiza 72438 enActualización SQL no funciona inserte

SQL Server Execution Times: 
    CPU time = 1359 ms, elapsed time = 7955 ms. 

ROWS AFFECTED(72438) 

¿No tengo ideas acerca de qué podría estar causando mi problema? Permisos, no lo creo? Espacio No lo creo porque se devolverá un Error?

consultas:

UPDATE [Sales].[dbo].[WeeklySummary] 
SET [CountryId] = I.CountryId 
    ,[CurrencyId] = I.CurrencyId 
    ,[WeeklySummaryType] = @WeeklySummaryTypeId  
    ,[WeeklyBalanceAmt] = M.WeeklyBalanceAmt + I.WeeklyBalanceAmt 
    ,[CurrencyFactor] = I.CurrencyFactor 
    ,[Comment] = I.Comment 
    ,[UserStamp] = I.UserStamp 
    ,[DateTimeStamp] = I.DateTimeStamp 
FROM 
    [Sales].[dbo].[WeeklySummary] M 
INNER JOIN 
    @WeeklySummaryInserts I 
    ON M.EntityId = I.EntityId 
    AND M.EntityType = I.EntityType 
    AND M.WeekEndingDate = I.WeekEndingDate 
    AND M.BalanceId = I.BalanceId 
    AND M.ItemType = I.ItemType 
    AND M.AccountType = I.AccountType 

y

INSERT INTO [Sales].[dbo].[WeeklySummary] 
    ([EntityId] 
    ,[EntityType] 
    ,[WeekEndingDate] 
    ,[BalanceId] 
    ,[CountryId] 
    ,[CurrencyId] 
    ,[WeeklySummaryType] 
    ,[ItemType] 
    ,[AccountType] 
    ,[WeeklyBalanceAmt] 
    ,[CurrencyFactor] 
    ,[Comment] 
    ,[UserStamp] 
    ,[DateTimeStamp]) 
SELECT 
    I.[EntityId] 
, I.[EntityType] 
, I.[WeekEndingDate] 
, I.[BalanceId] 
, I.[CountryId] 
, I.[CurrencyId] 
, @WeeklySummaryTypeId 
, I.[ItemType] 
, I.[AccountType] 
, I.[WeeklyBalanceAmt] 
, I.[CurrencyFactor] 
, I.[Comment] 
, I.[UserStamp] 
, I.[DateTimeStamp] 
FROM 
    @WeeklySummaryInserts I 
LEFT OUTER JOIN 
    [Sales].[dbo].[WeeklySummary] M 
    ON I.EntityId = M.EntityId 
    AND I.EntityType = M.EntityType 
    AND I.WeekEndingDate = M.WeekEndingDate 
    AND I.BalanceId = M.BalanceId 
    AND I.ItemType = M.ItemType 
    AND I.AccountType = M.AccountType 
WHERE M.WeeklySummaryId IS NULL 

ACTUALIZACIÓN

probar los consejos que aquí trabajaron durante un tiempo corro lo siguiente antes de mi llamada al procedimiento almacenado

UPDATE STATISTICS Sales.dbo.WeeklySummary; 
UPDATE STATISTICS Sales.dbo.ARSubLedger; 
UPDATE STATISTICS dbo.AccountBalance; 
UPDATE STATISTICS dbo.InvoiceUnposted 
UPDATE STATISTICS dbo.InvoiceItemUnposted; 
UPDATE STATISTICS dbo.InvoiceItemUnpostedHistory; 
UPDATE STATISTICS dbo.InvoiceUnpostedHistory; 
EXEC sp_recompile N'dbo.proc_ChargeRegister' 

Todavía se estanca en Insert Statement, que nuevamente inserta 0 filas.

+0

¿Se cuelga la inserción si se comenta la actualización? – Davidann

+3

No hay teoría sobre su problema específico, pero si está en SQL Server 2008 es posible que desee utilizar 'MERGE' para esto de todos modos. –

+0

Entonces, lo que realmente hice fue eliminar los datos que estaba actualizando. El primer intento 0 actualizaciones y todas las inserciones y funcionó bien. La segunda vez todas las actualizaciones y 0 inserciones funcionaron bien ahora. ¿Algunas ideas? Debería eliminar la pregunta Ahora estoy asustado de que esto suceda en la producción algún día. – Mike

Respuesta

2

Realmente solo hay algunas cosas que pueden estar sucediendo, y el truco aquí es eliminarlas en orden, desde la más simple hasta la más compleja.

PASO 1: Cree a mano un conjunto de XML para ejecutar que producirá exactamente una inserción y no actualizaciones, por lo que puede volver a "volver a lo básico" y establecer que el código sigue haciendo lo que espera, y el resultado es exactamente lo que esperas. Esto puede parecer tonto o innecesario, pero realmente necesita este control de realidad para comenzar.

PASO 2: Cree a mano un conjunto de XML que producirá un conjunto de insertos de tamaño medio, sin actualizaciones. En función de tu experiencia con la rutina, intenta encontrar algo que se ejecute en 3-4 segundos. Quizás 5000 filas. ¿Sigue comportándose como se esperaba?

PASO 3: Asumiendo que los pasos 1 y 2 pasen fácilmente, el siguiente problema más probable es el TAMAÑO DE LA TRANSACCIÓN. Si su actualización alcanza 74,000 filas en una sola declaración, entonces SQL Server debe asignar recursos para poder revertir las 74,000 filas en el caso de un aborto. En general, debe suponer que los recursos (y el tiempo) necesarios para mantener una transacción explotan exponencialmente a medida que aumenta el recuento de filas. Entonces, cree a mano un conjunto más de insertos que contenga 50,000 filas. Deberías encontrar que toma mucho más tiempo. Deja que termine ¿Son 10 minutos, una hora? Si tarda mucho tiempo pero termina, tiene un problema con TRANSACTION SIZE, el servidor se está ahogando tratando de realizar un seguimiento de todo lo que se requiere para deshacer la inserción en caso de falla.

PASO 4: Determine si su procedimiento almacenado completo está operando dentro de una única transacción implícita. Si es así, el asunto es completamente peor, porque SQL Server está rastreando todo lo necesario para deshacer las 74,000 actualizaciones y el ??? inserta en una sola transacción. Ver esta página:

http://msdn.microsoft.com/en-us/library/ms687099(v=vs.85).aspx

PASO 5: Si usted tiene una sola transacción implícita, puede.A) Desactívela, lo que puede ayudar a algunos, pero no solucionará del todo el problema, o B) dividir el sproc en dos llamadas separadas, una para las actualizaciones, y otra para las inserciones, de modo que al menos las dos estén en transacciones separadas.

PASO 6: Considere "fragmentar". Esta es una técnica para evitar la explosión de los costos de transacción. Teniendo en cuenta solo el INSERT para comenzar, usted ajusta el inserto en un ciclo que comienza y confirma una transacción dentro de cada iteración, y sale cuando las filas afectadas son cero. El INSERT se modifica para que solo saque las primeras 1000 filas de la fuente e insertarlas (que el número 1000 es algo arbitrario, puede encontrar que 5000 produce un mejor rendimiento, tiene que experimentar un poco). Una vez que INSERT afecta a cero filas, no hay más filas para manejar y el ciclo sale.

EDICIÓN RÁPIDA: El sistema de "fragmentación" funciona porque el rendimiento completo para un gran conjunto de filas se parece a un cuadrático. Si ejecuta un INSERT que afecta a un gran número de filas, el tiempo total para manejar todas las filas explota. Si, por el contrario, lo divide y va fila por fila, la sobrecarga de abrir y comprometer cada declaración hace que explote el tiempo total de todas las filas. En algún punto en el medio, cuando has fragmentado 1k filas por extracto, los requisitos de transacción están en su mínimo y la sobrecarga de abrir y comprometer la declaración es insignificante, y el tiempo total para manejar todas las filas es un mínimo .

0

Tuve un problema donde el proceso almacenado se volvía a compilar en el medio de la ejecución porque borraba filas de una tabla temporal. Mi situación no se parece a la tuya, pero la mía era tan extraña que leer sobre ella podría darte algunas ideas.

Unexplained SQL Server Timeouts and Intermittent Blocking

creo que debe publicar el procedimiento almacenado completa porque el problema no parece ser donde se piensa que es.

Cuestiones relacionadas