Administrar tamaños de lote de copia masiva

El propósito principal de un lote en las operaciones de copia masiva consiste en definir el ámbito de una transacción. Si no se establece un tamaño de lote, las funciones de copia masiva consideran una copia masiva completa como una transacción. Si se establece un tamaño de lote, cada lote constituye una transacción que confirma cuando finaliza el lote.

Si una copia masiva se realiza sin especificar ningún tamaño de lote y se produce un error, se revierte la copia masiva completa. La recuperación de una copia masiva de ejecución prolongada puede tardar mucho tiempo. Cuando se establece un tamaño de lote, la copia masiva considera cada lote como una transacción y confirma cada lote. Si se produce un error, sólo es necesario revertir el último lote pendiente.

El tamaño de lote también puede afectar a la sobrecarga de bloqueo. Al realizar una copia masiva en SQL Server, se puede especificar la sugerencia TABLOCK con bcp_control para adquirir un bloqueo de tabla en lugar de bloqueos de fila. El bloqueo de una única tabla se puede mantener con una sobrecarga mínima en una operación de copia masiva completa. Si no se especifica TABLOCK, los bloqueos se mantienen en las filas individuales y la sobrecarga de mantener todos los bloqueos durante la copia masiva puede reducir el rendimiento. Dado que los bloqueos sólo se mantienen mientras dura una transacción, la especificación de un tamaño del lote resuelve este problema ya que se genera periódicamente una confirmación que libera los bloqueos actuales.

El número de filas que conforman un lote puede tener efectos significativos en el rendimiento cuando se realiza la copia masiva de un gran número de filas. Las recomendaciones para el tamaño del lote dependen del tipo de copia masiva que se realiza.

  • Cuando realice una copia masiva en SQL Server, especifique la sugerencia TABLOCK de copia masiva y establezca un tamaño de lote grande.

  • Si no especifica TABLOCK, limite los tamaños de lote a un número menor que 1.000 filas.

Cuando la copia masiva se realiza a partir de un archivo de datos, el tamaño de lote se especifica mediante una llamada a bcp_control con la opción BCPBATCH antes de llamar a bcp_exec. Cuando la copia masiva se realiza a partir de variables de programa con bcp_bind y bcp_sendrow, el tamaño de lote se controla mediante una llamada a bcp_batch después de llamar a bcp_sendrow x veces, donde x es el número de filas de un lote.

Además de especificar el tamaño de una transacción, los lotes también afectan al envío de las filas al servidor a través de la red. Generalmente, las funciones de copia masiva almacenan en memoria caché las filas de bcp_sendrow hasta que se rellena un paquete de red y, a continuación, envían el paquete completo al servidor. Cuando una aplicación llama a bcp_batch, sin embargo, el paquete actual se envía al servidor independientemente de si se ha rellenado. La utilización de un tamaño de lote muy bajo puede reducir el rendimiento si da lugar al envío de numerosos paquetes parcialmente rellenados al servidor. Por ejemplo, la llamada a bcp_batch después de bcp_sendrow provoca que se envíe cada fila en un paquete independiente y, a menos que las filas sean muy grandes, desperdicia espacio en cada paquete. El tamaño predeterminado de los paquetes de red para SQL Server es 4 de KB, aunque una aplicación puede cambiar el tamaño mediante una llamada a SQLSetConnectAttr que especifique el atributo SQL_ATTR_PACKET_SIZE.

Otro efecto secundario de los lotes es que cada lote se considera un conjunto de resultados pendiente hasta que se completa con bcp_batch. Si se intenta realizar cualquier otra operación en un identificador de conexión mientras un lote está pendiente, el controlador ODBC de SQL Server Native Client emite un error con SQLSTATE = "HY000" y una cadena con el mensaje de error:

"[Microsoft][SQL Server Native Client] Connection is busy with
results for another hstmt."