2008-12-02 27 views
15

Estoy intentando insertar una gran cantidad de registros en SQL Server 2005 desde Vb.Net. Aunque la inserción funciona bien, hago todo lo posible para tratar de hacerlo lo más rápido posible. Actualmente, toma ~ 11 minutos para 100.000 registros. ¿Cuál sería el enfoque sugerido para insertar una gran cantidad de registros en SQL Server desde una aplicación?Inserción masiva en el servidor Sql

Mi enfoque actual es, básicamente, abrir la conexión, iterar a través de mi lista de información y desconectar declaraciones de inserción SQL individuales, y luego cerrar la conexión. ¿Alguien tiene una mejor sugerencia sobre cómo hacer esto?

Función actual:

Public Sub BatchInsert(ByVal ParamCollections As List(Of SqlParameter())) 

    Dim Conn As SqlConnection = New SqlConnection(DBHelper.DatabaseConnection) 
    Using scope As TransactionScope = New TransactionScope() 
    Using Conn 

     Dim cmd As SqlCommand = New SqlCommand("sproc_name", Conn) 

     Conn.Open() 
     cmd.CommandType = CommandType.StoredProcedure 

     For i = 0 To ParamCollections.Count - 1 

      cmd.Parameters.Clear() 
      cmd.Parameters.AddRange(ParamCollections(i)) 
      cmd.ExecuteNonQuery() 

     Next 

     Conn.Close() 
     scope.Complete() 
    End Using 
    End Using 

End Sub 

Respuesta

19

Utilice la clase SqlBulkCopy, será capaz de correr a través de esos 100K filas mucho más rápido que las inserciones individuales.

Ah, y si puede, le insto a implementar una clase con capacidad IDataReader, para alimentar el método SqlBulkCopy.WriteToServer(IDataReader), esto le permitirá producir datos secuencialmente, una fila a la vez. Si está importando desde un archivo de texto, por ejemplo, compilar algunos métodos IEnumerable<T> que usen yield return y convertirlo en un objeto IDataReader le permitirá alimentar los datos al servidor de forma muy natural.

Para contrarrestar la pérdida de la capacidad de restitución con BCP, puede transferir los datos a una tabla temporal y luego ejecutar las declaraciones INSERT INTO normales en el servidor, transfiriendo de forma masiva los datos de la tabla temporal a la tabla de producción. le permitirá usar una transacción para la última parte de transferencia, y aún se ejecutará mucho más rápido que sus declaraciones de inserción individuales originales.

EDITAR: y Here's an example (C#, pero debe ser fácil de convertir a VB.Net) del uso de la API de carga masiva.

+0

Siempre que el OP esté bien al no registrar estas transacciones, esto es genial. El uso de BCP eliminará la capacidad de deshacer los datos (no como realmente se usa la mayor parte del tiempo de todos modos). – StingyJack

+0

Estoy buscando en el Bulk Copy ahora. Parece que tendré que convertir mis datos en una DataTable para aprovechar la Copia masiva. ¿El proceso de creación y carga de DataTable compensará las ganancias de Copia de compilación? – Nathan

+0

No. El tiempo requerido para construir la tabla de datos será muy pequeño en comparación con el tiempo que está gastando ahora. –

0

Depende de cómo se implemente la clase de copia masiva. Pero hay una herramienta de línea de comandos incluida con las instalaciones de SQL Server que hace exactamente esto (probablemente sea el mismo). Se llama "bcp". Lo estoy usando ahora mismo y debería poder atravesar 100.000 filas en cuestión de segundos.

La documentación de MSDN se refiere a ella como la utilidad de "importación masiva".

1

También hay un proceso almacenado (llamado Bulk Insert) que hará el truco para ti .. Utiliza bcp debajo de las cubiertas.

la salida este enlace para ver la sintaxis

link text

2

Ponga sus datos para ser importados en un archivo csv y ejecute la utilidad bcp en los datos. No puede obtener más rápido con llamadas secuenciales insertando filas individuales a la vez, ciertamente necesita una utilidad masiva si desea rendimiento.

La clase SQLBulkCopy le permitirá transmitir todos los datos de una colección para que el servidor pueda procesar todo a la vez, eliminando el ir y venir. Entonces, si desea evitar la creación de archivos temporales (lo que yo haría), busque esa clase.

Tener solo la conexión abierta es un buen comienzo, pero aún tiene la carga de enviar una fila, tener SQL lo almacena, devolver un resultado y luego debe iterar a la siguiente fila.

11

Gracias a todos la ayuda, pude completar mi tarea. El SQLBulkCopy se ajusta perfectamente a mis necesidades (aunque hubo algunas otras sugerencias excelentes). Usando SqlBulkcopy, el tiempo pasó de 11 minutos a 45 segundos. No puedo creer la diferencia!

Para futuras referencias, aquí son unos pocos bits de información:

  • Para utilizar la copia masiva de SQL, los datos tienen que ser en forma de un conjunto de datos, DataReader, o DataTable. También se permite algo de XML.

código de implementación básica:

Public Sub PerformBulkCopy(ByVal dt As DataTable) 

    Using Conn As SqlConnection = New SqlConnection(DBHelper.DatabaseConnection) 
     Conn.Open() 

     Using s As SqlBulkCopy = New SqlBulkCopy(Conn) 

      s.DestinationTableName = "TableName" 
      s.WriteToServer(dt) 
      s.Close() 

     End Using 

     Conn.Close() 
    End Using 
End Sub 

enlace Muy informativo que he encontrado:

Using Sql Bulk Copy

Gracias a todos por la ayuda! Sinceramente lo aprecio

Cuestiones relacionadas