2010-02-26 9 views
12

Estoy construyendo un sistema para actualizar grandes cantidades de datos a través de varios canales CSV. Normalmente me gustaría hacer un ciclo de cada fila en el feed, hacer una consulta de selección para comprobar si el elemento ya existe e insertar/actualizar un elemento, dependiendo de si existe o no.Mejores prácticas para insertar/actualizar gran cantidad de datos en SQL Server 2008

Siento que este método no es muy escalable y podría dañar el servidor en fuentes más grandes. Mi solución es recorrer los elementos de manera normal, pero almacenarlos en la memoria. Luego, por cada 100 elementos, seleccione uno de esos 100 elementos y obtenga una lista de los elementos existentes en la base de datos que coincidan. A continuación, concatene las instrucciones de inserción/actualización y ejecútelas en la base de datos. Esto esencialmente reduciría los viajes a la base de datos.

¿Se trata de una solución suficientemente escalable y hay ejemplos de tutoriales sobre la importación de fuentes grandes en un entorno productivo?

Gracias

Respuesta

13

Al ver que se está utilizando SQL Server 2008, recomendaría este enfoque:

  • primera bulkcopy sus archivos CSV en una tabla de etapas
  • actualización de su tabla de destino de esa tabla de ensayo utilizando el comando MERGE

Consulte MSDN docs y great blog post sobre cómo usar el comando MERGE.

Básicamente, se crea un vínculo entre la tabla de datos actual y la tabla de ensayo en un criterio común (por ejemplo, una clave principal común), y luego se puede definir lo que hay que hacer cuando

  • las filas coinciden, p.ej la fila existe tanto en la tabla de origen como en la tabla de destino -> normalmente actualizaría algunos campos, o simplemente ignoraría todos juntos
  • la fila de la fuente no existe en el destino -> típicamente un caso para una inserción

se podría tener una declaración MERGE algo como esto:

MERGE TargetTable AS t 
USING SourceTable AS src 
ON t.PrimaryKey = src.PrimaryKey 

WHEN NOT MATCHED THEN 
    INSERT (list OF fields) 
    VALUES (list OF values) 

WHEN MATCHED THEN 
    UPDATE 
    SET (list OF SET statements) 
; 

por supuesto, la cláusula ON puede ser mucho más complicado si es necesario. Y, por supuesto, sus declaraciones WHEN también pueden ser más complejas, p.

WHEN MATCHED AND (some other condition) THEN ...... 

y así sucesivamente.

MERGE es un nuevo comando muy poderoso y muy útil en SQL Server 2008 - ¡úselo, si puede!

2

Una forma es cargar el archivo CSV en un DataTable (o más probablemente un DataReader) y luego de golpe por lotes en los resultados utilizando SqlBulkCopy -

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx

Es bastante eficiente y que pueda hacer un mapeo de columna Sugerencia: cuando mapea columnas con SqlBulkCopy, distinguen entre mayúsculas y minúsculas.

0

Otro enfoque sería escribir un procedimiento almacenado en el servidor Net en el servidor para operar en todo el archivo ...

Sólo si necesita más control que la solución de Kris Krause aunque - Soy un gran fan de mantenerlo simple (y reutilizable) donde podamos ...

0

¿Necesitas rodar el tuyo aquí? ¿Sería posible proporcionar los datos de tal manera que SQL Server pueda usar la importación masiva para cargarlo y luego tratar con los duplicados en la base de datos una vez que se complete la importación?

Cuando se trata de levantar objetos pesados ​​con una gran cantidad de datos, mi experiencia tiende a ser que trabajar en la base de datos tanto como sea posible es mucho más rápido y requiere menos recursos.

2

Su camino es la peor solución posible. En general, no debe pensar en términos de recorrer los registros individualmente. Solíamos tener una herramienta de importación desarrollada por la compañía que recorre los recinords, tomaría de 18 a 20 horas cargar un archivo con más de un millón de registros (algo que no era una ocurrencia frecuente cuando se construyó, pero que es muchas veces una día que ocurre ahora).

Veo dos opciones: Primero use la inserción masiva para cargar en una tabla de etapas y haga la limpieza que necesite en esa tabla. ¿Cómo estás determinando si el registro existe al fin? Debería poder construir una actualización basada en conjuntos uniéndose a la tabla de etapas en aquellos campos que determinan la actualización. A menudo tengo una columna agregada a mi tabla de etapas para la identificación del registro con el que coincide y la rellene a través de una consulta y luego hago la actualización. Luego haces una inserción de los registros que no tienen una identificación correspondiente. Si tiene demasiados registros para hacer todos a la vez, es posible que desee ejecutar en lotes (que sí es un bucle), pero haga que los lotes sean considerablemente más grandes que 1 registro a la vez (generalmente comienzo con 2000 y luego con base en el el tiempo que toma para determinar si puedo hacer más o menos en el lote).

Creo que 2008 también tiene una declaración de fusión, pero todavía no he tenido la oportunidad de usarlo. Búscalo en libros en línea.

La alternativa es usar SSIS optimizado para la velocidad.SSIS es algo complejo y la curva de aprendizaje es empinada.

+0

+1 para usar BULK INSERT & MERGE –

+0

Gracias por su sugerencia. El motivo por el que recorro cada elemento es porque necesito realizar alguna validación y lógica de formateo antes de agregarlo a la base de datos. Esto luego se retransmite al usuario si hay algún problema con el feed en sí. Aunque me gusta la idea de fusionar los datos, investigaré eso. – markvpc

+0

También puede hacer la validación y el formateo de forma sencilla. Pasar por los registros individuales es casi siempre una mala elección y no debe considerar hacerlo hasta que todas las otras opciones hayan sido eliminadas. – HLGEM

Cuestiones relacionadas