¿Cuál es el tamaño de lote recomendado para SqlBulkCopy?

87

¿Para qué es el tamaño de lote recomendado SqlBulkCopy? Estoy buscando una fórmula general que pueda usar como punto de partida para ajustar el rendimiento.

Jonathan Allen
fuente

Respuestas:

97

Tengo una utilidad de importación en el mismo servidor físico que mi instancia de SQL Server. Usando un IDataReaderarchivo personalizado , analiza archivos planos y los inserta en una base de datos usando SQLBulkCopy. Un archivo típico tiene alrededor de 6 millones de filas calificadas, con un promedio de 5 columnas de texto decimal y breve, aproximadamente 30 bytes por fila.

Dado este escenario, encontré que un tamaño de lote de 5,000 es el mejor compromiso de velocidad y consumo de memoria. Empecé con 500 y experimenté con más grandes. Descubrí que 5000 es 2,5 veces más rápido, en promedio, que 500. Insertar los 6 millones de filas lleva unos 30 segundos con un tamaño de lote de 5000 y unos 80 segundos con un tamaño de lote de 500.

10,000 no fue mediblemente más rápido. Subir a 50.000 mejoró la velocidad en algunos puntos porcentuales, pero no vale la pena aumentar la carga en el servidor. Por encima de 50.000 no se observaron mejoras en la velocidad.

Esta no es una fórmula, pero es otro punto de datos que puede utilizar.

Alric
fuente
3
Una cosa a considerar es si la tabla está vacía y tiene índices. En esos casos, es posible que desee cargar todo en un lote como se menciona aquí: technet.microsoft.com/en-us/library/ms177445(v=sql.105).aspx "Si realiza una importación masiva de datos en una tabla vacía con índices y especifica el tamaño del lote, la tabla se vuelve no vacía después del primer lote. A partir del segundo lote, los datos se registran por completo. Para las tablas indexadas vacías, considere realizar la importación masiva en un solo lote ".
Sal
SqlBulkCopy transmite los datos desde la fuente (por ejemplo, DataTable) a Sql, entonces, ¿qué "aumento de carga en el servidor" tiene en un tamaño de lote grande? (por ejemplo, 50.000)
BornToCode
29

Este es un tema que también he estado investigando. Estoy buscando optimizar la importación de archivos CSV grandes (más de 16 GB, más de 65 millones de registros y en crecimiento) en una base de datos de SQL Server 2005 utilizando una aplicación de consola C # (.Net 2.0). Como Jeremy ya ha señalado , deberá realizar algunos ajustes para sus circunstancias particulares, pero le recomendaría que tenga un tamaño de lote inicial de 500 y valores de prueba tanto por encima como por debajo de este.

Recibí la recomendación de probar valores entre 100 y 1000 para el tamaño de lote de esta publicación del foro de MSDN y era escéptico. Pero cuando probé lotes de entre 100 y 10,000, descubrí que 500 era el valor óptimo para mi aplicación. AquíSqlBulkCopy.BatchSize también se recomienda el valor 500 para .

Para optimizar aún más su operación de SqlBulkCopy, consulte este consejo de MSDN ; Creo que el uso de SqlBulkCopyOptions.TableLock ayuda a reducir el tiempo de carga.

MagicAndi
fuente
Creo que ejecutar el comando de copia masiva en el servidor mismo probablemente sea más rápido.
Capitán Kenpachi
16

Como han dicho otros, depende de su entorno, específicamente el volumen de filas y la latencia de la red.

Personalmente, comenzaría estableciendo la BatchSizepropiedad en 1000 filas y vería cómo funciona. Si funciona, sigo duplicando el número de filas (por ejemplo, a 2000, 4000, etc.) hasta que se agota el tiempo de espera.

De lo contrario, si se agota el tiempo de espera en 1000, entonces disminuyo el número de filas a la mitad (por ejemplo, 500) hasta que funcione.

En cada caso, sigo duplicando (si tiene éxito) o reduciendo a la mitad (si falla) la diferencia entre cada uno de los dos últimos tamaños de lote intentados hasta encontrar un punto óptimo.

El otro factor a considerar es cuánto tiempo se tarda en copiar un solo lote de filas. Se producirán tiempos de espera si el lote de filas que se está copiando excede la BulkCopyTimeoutpropiedad que por defecto es de 30 segundos. Puede intentar duplicar la BulkCopyTimeoutpropiedad a 60 segundos. Esto permite un período de tiempo más largo para copiar un conjunto más grande de filas de lote. Por ejemplo, un lote de 50.000 filas puede tardar alrededor de 40 segundos superando el límite de tiempo de 30 segundos, por lo que aumentarlo hasta 60 segundos podría ayudar con el rendimiento.

Rayo
fuente
4

Todo esto depende de su implementación.

¿Qué tipo de velocidad puede esperar en su red? ¿Lo está utilizando en Forms o ASP.Net? ¿Necesita alertar al usuario del progreso? ¿Cuál es el tamaño del trabajo total?

En mi experiencia, ejecutar una copia masiva sin un tamaño de lote especificado causará problemas de tiempo de espera. Me gusta comenzar con algo así como 1000 registros y hacer algunos ajustes a partir de ahí.

Jeremy
fuente
Velocidad: Varía, WebForms: Sí, ASP.NET: Sí, Tablas anchas: Sí, Tablas estrechas, Sí. Miles de filas: sí. Millones de filas: sí. Si puedes pensar en un escenario, probablemente lo estoy haciendo.
Jonathan Allen
1
Entonces tengo que ceñirme a mi respuesta anterior. No creo que haya una bala de plata.
Jeremy
-1

había probado varios tamaños, en mi caso 5000 era bueno

Un Mustapha
fuente