Obtener filas insertadas con SqlBulkCopy

linq-to-sql sqlbulkcopy sql-server transactions

Pregunta

Estoy cambiando parte de mi código de Linq a Sql para usar SqlBulkCopy, y el problema es que necesito hacer dos inserciones de varios miles de filas en dos tablas.

El servicio toma su lote de 10,000 enlaces (importados de sitemap, constructores de enlaces de retroceso, etc.), y los corta en fuentes RSS de X por fuente para la agregación. El problema es que ya tengo una tabla de 32 millones de filas . Si estoy haciendo inserciones de linq a sql, se tarda entre 5 y 10 minutos en depender del tráfico del sitio para cargar 10,000 enlaces.

La estructura es muy básica.

Fuentes : Id bigint (PK), Título varchar (1000), Descripción varchar (1000), Fecha de publicación, Fecha agregada nula, Varchar de código corto (8) [anticuado, no se inserta más, pero se usa para datos heredados]

Elementos : ID bigint (PK), FeedId bigint (FK), Título varchar (1000), Descripción varchar (1000), Fecha de publicación, ShortCode varchar (8) [anticuado, no se ha insertado más, pero se usa para datos heredados], Bigid corto nulo [actualizado después de insertar a Id igual (usado en la partición)]

FutureItems : ID bigint (PK), FeedId bigint (FK), Título varchar (1000), Descripción varchar (1000), Fecha de publicación, ShortCode varchar (8) [anticuado, no se inserta más, pero se usa para datos heredados], BigId bigint nulo [actualizado después de insertar a Id igual (usado en la partición)]

OldItems : ID bigint (PK), FeedId bigint (FK), Título varchar (1000), Descripción varchar (1000), Fecha de publicación, ShortCode varchar (8) [anticuado, no se ha insertado más, pero se usa para datos heredados], BigId bigint nulo [actualizado después de insertar a Id igual (usado en la partición)]

Por lo tanto, si tiene un tamaño de fuente de 20, obtiene 500 inserciones en la tabla de Fuentes, luego 10000 insertadas en la tabla de Artículos, y luego se ejecutan las actualizaciones para establecer el Id. Corto igual al ID. Una vez por noche, se ejecuta un trabajo que separa los datos en las otras dos tablas y cambia los elementos futuros a la tabla Artículos.

Leí que SqlBulkCopy puede hacer 20 millones de filas en cuestión de minutos, pero no puedo encontrar ningún buen ejemplo de hacerlo en varias tablas con una restricción FK.

Nuestro servidor SQL es un "monstruo" especialmente para esta aplicación. Es SQL 2008 R2 Web, Windows 2008 R2 Enterprise, 12GB Ram, Dual 4 core Xeons @ 2.8ghz.

Nuestro servidor web es un clon sin el servicio de base de datos.

La CPU ejecuta aproximadamente el 85% al ​​insertar enlaces, y la base de datos llena la RAM.

Si SqlBulkCopy no es bueno, cualquier sugerencia es bienvenida, tenemos clientes de pago que se están enojando, y no soy un DBA, solo un simple programador.

Respuesta aceptada

SqlBulkCopy es de hecho más rápido que las inserciones comunes. Pero es más rápido ya que puede transformar un trabajo que ejecuta 1000 inserciones por segundo en una que hace 10000 / seg. Si solo puede hacer 10000 enlaces en 10 minutos, debe tener diferentes problemas, algo que es poco probable que la copia masiva resuelva.

Primero debe investigar por qué se tarda tanto tiempo en insertar 10000 enlaces. Solo después de comprender que puede hacer una llamada que determine si el cambio a SqlBulkCopy es una solución. Entiendo que usted no es un DBA, pero le enviaré un documento técnico 'dbaish' para solucionar problemas de rendimiento de SQL Server: Esperas y colas . Esta no es una solución de receta para cortar galletas, es en realidad una metodología que le enseñará cómo identificar cuellos de botella de rendimiento en SQL Server.

Y para responder a su pregunta: ¿cómo se usa SqlBulkCopy cuando hay restricciones? La pregunta más genérica es ¿cómo se realizan las operaciones de inserción masiva cuando existen restricciones? Para volúmenes serios, uno realmente desactiva las restricciones, realiza las cargas masivas y luego habilita las restricciones. Para operaciones en línea más simplificadas con un tiempo de inactividad mínimo (la base de datos está básicamente 'inactiva' para el período en que se deshabilitan las restricciones), se usa una estrategia diferente, es decir, carga previamente los datos en las tablas de etapas, lo valida y luego lo cambia con una operación del conmutador de partición, consulte Transferencia de datos de manera eficiente mediante el uso del conmutador de partición .


Respuesta popular

Creo que su problema real con solo usar una inserción masiva simple es que necesita los identificadores de alimentación de la inserción inicial para las otras tablas. Esto es lo que yo haría. Use inserto a granel para insertar en una tabla de preparación. Luego use un proceso almacenado para hacer las inserciones en la tabla real de una manera basada en conjuntos. Puede usar la cláusula de salida en la inserción inicial en la tabla de alimentación para recuperar una variable de tabla con los identificadores de alimentación que necesita para las inserciones en las otras tablas.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué