Detalle de Objetos para la Copia de Datos

ibb.Cargar_Tablas_Secuencias e ibb.Cargar_Tablas_Secuencias_Copia_Origen

En las bases de datos origen y destino se crea la tabla 'ibb.Cargar_Tablas_Secuencias'. En ella se almacenan las secuencias existentes en las base de datos y la información necesaria para reinicializarlas. Una vez copiados los datos, las secuencias deben comenzar con un valor que permita que el sistema se ejecute sin problemas.

Campo Tipo NULL Restricción Descripción
SchemaSeqName sysname NOT NULL Esquema de la Secuencia
SequenceName sysname NOT NULL Nombre de la Secuencia
SchemaSequenceName CONCAT(QUOTENAME(SchemaSeqName), N'.', QUOTENAME(SequenceName)) PERSISTED NOT NULL Esquema y Nombre de la Secuencia
SchemaName sysname NULL Esquema de la tabla
TableName sysname NULL Nombre de la Tabla
ColumnName sysname NULL Nombre del campo utilizado para reinicializar la Secuencia.
SchemaTableName IIF(SchemaName IS NULL OR TableName IS NULL, NULL, CONCAT(QUOTENAME(SchemaName), N'.', QUOTENAME(TableName))) PERSISTED Esquema y Nombre de la tabla
QueryAlternateToColumn nvarchar(max) NULL CHECK CONSTRAINT Cargar_Tablas_Secuencias_ColumnOrQuery_CHK CHECK(
    (QueryAlternateToColumn IS NULL AND SchemaName IS NOT NULL AND TableName IS NOT NULL AND ColumnName IS NOT NULL) OR
    (QueryAlternateToColumn IS NOT NULL AND SchemaName IS NULL AND TableName IS NULL AND ColumnName IS NULL) OR
    (QueryAlternateToColumn IS NULL AND SchemaName IS NULL AND TableName IS NULL AND ColumnName IS NULL))
Si la secuencia no se reinicializa a partir de un campo de una tabla se debe suministrar un conjunto de instrucciones que permita dicha acción

Para la reinicialización de una secuencia que realiza el papel de un IDENTITY, sólamente hay que indicar el campo en esta tabla. Insert Bulk Bestia obtendrá el máximo + 1 de dicho campo y con ese valor se reinicializará dicha secuencia. Para ello, se han de rellenar los campos 'SchemaName', 'TableName', y 'ColumnName' que definen dicho campo, y dejar a NULL el campo 'QueryAlternateToColumn' de la tabla 'ibb.Cargar_Tablas_Secuencias'.

En otras ocasiones, la secuencia, aunque se encuentre asociada a un campo de una tabla, su valor de reinicialización no se puede obtener a partir del máximo, sino que se necesita una sentencia para obtener su máximo. Dicha sentencia deberá incluirse en el campo 'QueryAlternateToColumn' y dejar a nulos los campos de 'ibb.Cargar_Tablas_Secuencias' indicados anteriormente.

En este caso, la sentencia que se ha de introducir debe comenzar exactamente por "SELECT @output = ". En @output se debe dejar el valor con el cual se ha de reinicializar la secuencia, es decir, el primer valor que ha de tomar la secuencia.

Ejemplos:

  • Secuencia independiente:
    SELECT @output = 1
  • Secuencia utilizada para insertar en dos tablas:
    SELECT @output = ISNULL(MAX(Tabla.Campo), 0) + 1
    FROM (
        SELECT MAX(Campo1) Campo FROM dbo.Tabla1
        UNION ALL
        SELECT MAX(Campo2) Campo FROM dbo.Tabla2
    ) AS Tabla
  • Secuencia utilizada como parte de una cadena de caracteres:
    Campo
    00000000000001K
    00000000000002K
    00000000000004K
    00000000000007K
    00000000000016K
    00000000000017K

    SELECT @output = ISNULL(MAX(CONVERT(INT, SUBSTRING(Campo, 1, LEN(Campo) - 1))), 0) + 1 FROM dbo.Tabla

ibb.Cargar_Tablas_Actualiza_Secuencias

Procedimiento almacenado para actualizar la tabla 'ibb.Cargar_Tablas_Secuencias' en el origen y en el destino.

Añade las secuencias nuevas y elimina las que han desaparecido. Insert Bulk Bestia parará la ejecución de la carga de datos si este procedimiento detecta que hay secuencias nuevas desde la última vez que se ejecutó. De esta forma, permitirá la modificación de la tabla 'ibb.Cargar_Tablas_Secuencias' para definir cómo se debe reinicializar cada secuencia.

ibb.Cargar_Tablas e ibb.Cargar_Tablas_Copia_Origen

En las bases de datos origen y destino se crean estas dos tablas. En anteriores apartados se describió la utilidad de dichas tablas. Aquí, se describirá el detalle de las mismas y la utilidad de determinados campos.

Campo Tipo NULL Restricción Descripción
Configuration nvarchar(512) NOT NULL Nombre de la configuración
SchemaName_Origen sysname NOT NULL Esquema de la tabla Origen
TableName_Origen sysname NOT NULL Nombre de la tabla origen
SchemaTableName_Origen CONCAT(QUOTENAME(SchemaName_Origen), N'.', QUOTENAME(TableName_Origen)) PERSISTED NOT NULL Esquema y Nombre de la tabla origen
SelectCampos_Oracle_Origen nvarchar(max) NOT NULL Reservado para el futuro
SelectCampos_SQLServer_Origen nvarchar(max) NOT NULL Cláusula SELECT que indican los campos a copiar de la tabla origen. Aquí podrá realizar las transformaciones deseadas a los datos. El orden de los campos deberá ser el mismo que el utilizado en la cláusula SELECT del destino.
Condition_Segment_Oracle_Origen nvarchar(max) NULL Reservado para el futuro
Condition_Segment_SQLServer_Origen nvarchar(max) NULL Cláusula WHERE para el filtrado de los registros en la tabla origen. Define los registros que se copiarán al destino. Normalmente, debería coincidir con el filtro utilizado en la tabla origen.
SchemaName_Destino sysname NOT NULL Esquema de la tabla destino
TableName_Destino sysname NOT NULL Nombre de la tabla destino
SchemaTableName_Destino CONCAT(QUOTENAME(SchemaName_Destino), N'.', QUOTENAME(TableName_Destino)) PERSISTED NOT NULL Esquema y Nombre de la tabla destino
SelectCampos_Oracle_Destino nvarchar(max) NOT NULL Reservado para el futuro
SelectCampos_SQLServer_Destino nvarchar(max) NOT NULL Cláusula SELECT que indican los campos destino en la tabla destino. El orden de los campos deberá ser el mismo que el utilizado en la cláusula SELECT del origen.
Condition_Segment_Oracle_Destino nvarchar(max) NULL Reservado para el futuro
Condition_Segment_SQLServer_Destino nvarchar(max) NULL Cláusula WHERE para el filtrado de los registros en la tabla destino. Define los registros que se eliminarán en caso de reintentos. Normalmente, debería coincidir con el filtro utilizado en la tabla origen.
SegmentID tinyint NOT NULL Cargar_Tablas_SegmentID_DEF DEFAULT (0) Identificador del segmento. Utilizado para la segmentación de tablas grandes, permitiendo la carga de la tabla en paralelo.
RowsCount int NULL Nº de filas de la tabla origen
DataKb int NULL Espacio (aproximado) ocupado por los datos de la tabla.
IndexSize int NULL Espacio (aproximado) ocupado por los índices de la tabla.
Durability tinyint NOT NULL Cargar_Tablas_Durability_DEF DEFAULT (0) sys.tables
Is_memory_optimized bit NOT NULL Cargar_Tablas_Is_memory_optimized_DEF DEFAULT (0) sys.tables
ClasificacionTabla tinyint NOT NULL Cargar_Tablas_ClasificacionTabla_DEF DEFAULT (0) Identificador del grupo de tablas al que pertenece la tabla. Permite realizar una clasificación de tablas.
CargarTabla tinyint NOT NULL Cargar_Tablas_CargarTabla_DEF DEFAULT (0) Flag que indica si los datos de la tabla se han de copiar.
Resultado_CargarTabla tinyint NULL Resultado de la copia de datos de la tabla
FilasCopiadas int NULL Filas trasvasadas desde el origen al destino

El ejemplo siguiente se describe la utilidad de cada uno de los campos. En él, solamente se muestran los campos más relevantes de la tabla 'ibb.Cargar_Tablas' y se detalla el origen, el destino y la selección de la carga.

Selección del Origen:

SchemaTableName_Origen SelectCampos_SQLServer_Origen Condition_Segment_SQLServer_Origen
[dbo].[Tabla1] SELECT [Campo1] * 100 AS Campo1, [Campo2], [Campo3] NULL
[dbo].[Tabla2] SELECT [Campo1], [Campo2], [Campo3] Campo3 < CONVERT(DATETIME2,'01/01/2013',103)
[dbo].[Tabla2] SELECT [Campo1], [Campo2], [Campo3] Campo3 >= CONVERT(DATETIME2,'01/01/2013',103) AND Campo3 < CONVERT(DATETIME2,'01/01/2019',103)
[dbo].[Tabla2] SELECT [Campo1], [Campo2], [Campo3] Campo3 >= CONVERT(DATETIME2,'01/01/2019',103)

En el origen se tienen 2 tablas:

La primera tiene 3 campos y al primero se le ha aplicado una transformación. Cuando Insert Bulk Bestia genera automáticamente estatabla, este campo se rellenaría con "SELECT [Campo1], [Campo2], [Campo3]", sin embargo, ya sea manualmente, o bien, con el procedimiento almacenado 'ibb.Cargar_Tablas_Acciones_Programables_Origen' se puede modificar dicha cláusula.

La segunda tabla se ha segmentado para poder realizar una carga en paralelo de dichos segmentos, acelerando así la carga de dicha tabla. La segmentación se ha realizado utilizando el "Campo3", por lo que sería muy recomendable que dicho campo tuviese el correspondiente índice que facilitase la selección de registros según indican las cláusulas WHERE.

Selección del Destino:

SchemaTableName_Destino SelectCampos_SQLServer_Destino Condition_Segment_SQLServer_Destino
[dbo].[Tabla1] SELECT [Campo1], [Campo3] NULL
[dbo].[Tabla2] SELECT [Campo1], [Campo2], [Campo3] Campo3 < CONVERT(DATETIME2,'01/01/2013',103)
[dbo].[Tabla2] SELECT [Campo1], [Campo2], [Campo3] Campo3 >= CONVERT(DATETIME2,'01/01/2013',103) AND Campo3 < CONVERT(DATETIME2,'01/01/2019',103)
[dbo].[Tabla2] SELECT [Campo1], [Campo2], [Campo3] Campo3 >= CONVERT(DATETIME2,'01/01/2019',103)

En el destino también se tienen las mismas tablas. Sin embargo, a la primera tabla se le ha eliminado el "Campo2", por lo que la correspondencia entre campos será:

Campo1(Campo1 * 100) -> Campo1 y Campo2 -> Campo3

El operador deberá comprobar la compatibilidad de datos entre Campo2 y Campo3 y si esa asignación no es correcta, debería modificar la cláusula SELECT del origen o eliminar el "Campo3" de la cláusula SELECT del destino.

Se ha de tener en cuenta de que en las cláusulas SELECT del destino no se puede aplicar ninguna transformación, ya que simplemente se utiliza para indicar cuáles son los destinos de cada campo del origen. Las transformaciones de datos se han de realizar en las cláusulas SELECT del origen.

Como en el origen, en la "Tabla2" se ha de realizar la correspondiente segmentación de la tabla, y añadir las correspondientes cláusulas WHERE que definen los segmentos de datos. Ello es necesario por dos motivos:

  • Cuando se deba cargar un segmento, en el destino se ha de poder realizar el vaciado de dicho segmento.
  • Cuando se produzca un error (un corte de red, por ejemplo) e Insert Bulk Bestia reintente la carga de dicho segmento, ha de poder eliminar los registros ya copiados en dicho segmento para volver a empezar.

Al igual que en la tabla origen, es deseable que los campos utilizados en la segmentación de la tabla destino tuviesen el/los índices necesarios para incrementar la eficiencia en la selección de registros. Así, en una nueva ejecución de la copia de datos, el vaciado del segmento será eficiente.

Sin embargo, en el caso de un reintento de carga de un determinado segmento por que ha fallado, Insert Bulk Bestia debe eliminar todos los registros del segmento para volverlos a cargar. En este caso, los índices puede que no existan debido a la lógica implementada en Insert Bulk Bestia. Si esto ocurre, es muy posible que dicho borrado sea excesivamente lento.

La lógica implementada en Insert Bulk Bestia para la eliminación de índices es:

  • No elimina los índices cluster de aquellas tablas en que el campo 'DataKb' de 'ibb.Cargar_Tablas' es mayor que el umbral indicado en 'Tamaño (KB) mínimo para no eliminar índice Cluster' del Panel Carga.
  • Para aquellas tablas que tienen habilitado el seguimiento de cambios por CDC, no elimina ningún índice utilizado por el seguimiento de cambios, ni su índice cluster.
    Seguimiento de cambios CDC: La base de datos tiene en 'sys.databases' el campo 'is_cdc_enabled' a 1 y la tabla tiene en 'sys.tables' el campo 'is_tracked_by_cdc' a 1.
  • Para aquellas tablas que tienen habilitado el seguimiento de cambios por CT, no elimina la Primary Key, ni su índice cluster. Seguimiento de cambios CT: La tabla aparece en 'sys.change_tracking_tables'
  • No elimina ningún índice de aquellas tablas que Insert Bulk Bestia no ha truncado previamente. Insert Bulk Bestia trunca una tabla previamente cuando:
    • Se desean cargar todos los segmentos de la tabla y la tabla no es una tabla optimizada para memoria.
    • Si los segmentos que se desean cargar abarcan todos los registros que contiene la tabla y la tabla no es una tabla optimizada para memoria.

En otras palabras, es bastante probable que Insert Bulk Bestia elimine los índices de las tablas segmentadas con el fin de acelerar la carga.

Selección de la Carga:

SegmentID ClasificacionTabla CargarTabla Resultado_CargarTabla
0 0 1 1
1 5 0 NULL
2 5 0 NULL
30 50 1 1

El campo 'SegmentID' se utiliza para indicar que una tabla se encuentra segmentada. Estrategia de normal de segmentación:

  • Si una tabla no está segmentada, este campo debería contener el valor 0.
  • Si está segmentada, el primer segmento debería contener el valor 1.
  • El último segmento debería contener un valor alto, por ejemplo, 100. Esto permitirá añadir segmentos intermedios cuando sea necesario, es decir, a medida que la tabla vaya creciendo.
Insert Bulk Bestia sólo utiliza este campo para obtener el orden en que los segmentos serán cargados.

El campo 'ClasificacionTabla' se utiliza para realizar un agrupamiento de tablas. Por ejemplo, el valor 1 puede indicar que son tablas maestras, el valor 2 puede indicar que son tablas temporales, las cuales raramente se desean copiar de una base de datos a otra, etc. Generalmente, al último segmento de las tablas segmentadas se le suele dar una clasificación diferente al resto de segmentos. De esta forma, se puede decirdir que sólo se copien los datos del último segmento de las tablas grandes, ya que sólo interesan para las pruebas los últimos datos introducidos y no la tabla entera.

Insert Bulk Bestia pondrá un 0 en este campo cuando aparezcan nuevas tablas desde la última vez que se ejecutó. Así, es conveniente repasar la clasificación de las tablas cada vez que la estructura de la base de datos se modifique.

Este campo, 'ClasificacionTabla', es el utilizado en 'Clasificaciones de Tablas para Cargar' del Panel Carga del interfaz de usuario. Allí, el usuario podrá indicar qué tablas desea copiar de una base de datos a otra. En este ejemplo, podría indicar que desea copiar las tablas con clasificación 0 y 50.

El campo 'CargarTabla' lo rellena Insert Bulk Bestia para indicar qué tablas y/o segmentos van a ser copiados. Lo realiza en el paso 10 indicado en el apartado Algoritmo de Trasvase de Datos. Marcará con un 1 las tablas a cargar y con un 0 el resto. Este paso 10 se puede obviar si se desmarca la opción 'Selección de Tablas por Campo "Clasificación"' del Panel Carga del interfaz de usuario. Entonces, podría usar ibb.Cargar_Tablas_Acciones_Programables_Destino_Iniciales para realizar esta acción.

El campo 'Resultado_CargarTabla' contendrá el resultado de la copia de datos. Un 1 significa que la copia ha sido un éxito. Un valor distinto de 1 indica lo contrario. Este campo es el utilizado por Insert Bulk Bestia para realizar los reintentos indicados en 'Nº de Reintentos para la Carga de Datos' del Panel Carga del interfaz de usuario.

ibb.Cargar_Tablas_Actualiza

Procedimiento almacenado creado en las bases de datos origen y destino. Es el procedimiento almacenado utilizado para la actualización de la tabla ibb.Cargar_Tablas.

Aunque el usuario puede modificarlo para adaptarlo a sus necesidades concretas, se recomienda no hacerlo y utilizar otras vías para ello. Insert Bulk Bestia ofrece los siguientes tres procedimientos almacenados para tal fin.

ibb.Cargar_Tablas_Acciones_Programables_Origen

Procedimiento almacenado creado solamente en la base de datos origen. Se ejecuta en el paso 3 del Algoritmo de Trasvase de Datos.

El objetivo de las acciones programadas en este procedimiento almacenado debe ser el ajuste "fino" y automático de los SELECT y WHERE para la base de datos origen, así como la realización de una clasificación automática de las tablas.

ibb.Cargar_Tablas_Acciones_Programables_Destino_Iniciales

Procedimiento almacenado creado en las bases de datos origen y destino. Se ejecuta en el paso 9 del Algoritmo de Trasvase de Datos.

El objetivo de las acciones programadas en este procedimiento almacenado debe ser el ajuste "fino" y automático de los SELECT y WHERE para la base de datos destino, así como la realización de una clasificación automática de las tablas. Otra de las utilidades puede ser la de adaptar el contenido de determinadas vistas que contengan información asociada a la instancia de destino. También puede utilizarse para marcar aquellas tablas que se desean cargar cuando se desee que Insert Bulk Bestia no realice dichaacción.

Como ya se ha descrito en apartados anteriores, el objetivo de crear este procedimiento almacenado en el origen, si no existe previamente, es el de que el usuario modifique su contenido en dicha base de datos, de tal forma que cuando traslade la estructura al destino, en dicha estructura vayan los cambios realizados y, por tanto, no tenga que desperdiciar tiempo en programar este procedimiento almacenado una y otra vez.

ibb.Cargar_Tablas_Acciones_Programables_Destino_Finales

Procedimiento almacenado creado en las bases de datos origen y destino. Se ejecuta en el paso 15 del Algoritmo de Trasvase de Datos.

El objetivo de las acciones programadas en este procedimiento almacenado debe ser el ajuste "fino" y automático de los datos copiados, como la ocultación de información confidencial, ajustes de "paths" al cambiar de entorno, etc.

Como ya se ha descrito en apartados anteriores, el objetivo de crear este procedimiento almacenado en el origen, si no existe previamente, es el de que el usuario modifique su contenido en dicha base de datos, de tal forma que cuando traslade la estructura al destino, en dicha estructura vayan los cambios realizados y, por tanto, no tenga que desperdiciar tiempo en programar este procedimiento almacenado una y otra vez.

ibb.Cargar_Tablas_Triggers

Tabla creada en la base de datos de destino. En ella se indican los triggers existentes en la base de datos y el estado en que se encuentran.

Campo Tipo NULL Restricción Descripción
SchemaName sysname NOT NULL Esquema de la Tabla del Trigger
TableName sysname NOT NULL Nombre de la Tabla del Trigger
TriggerName sysname NOT NULL Nombre del Trigger
SchemaTableName CONCAT(QUOTENAME(SchemaName), N'.', QUOTENAME(TableName)) PERSISTED NOT NULL Esquema y Nombre de la Tabla del Trigger
Is_Disabled bit NOT NULL Flag que indica si el Trigger se encuentra deshabilitado.

Dado que se va a realizar una copia de datos desde una Base de Datos de Origen a otra de Destino, cuya estructura se supone que es una réplica de la primera, también se supondrá que los datos que se van a copiar ya se encuentran validados. Por eso, la deshabilitación de las validaciones de los datos no debería suponer ningún problema.

Esto permitirá realizar una carga de datos, por así decirlo, desordenada, es decir, sin tener en cuenta la estructura lógica de la base de datos, lo cual implicaría realizar la carga en un determinado orden.

Posteriormente, se volverán a reestablecer las validaciones, de forma que la posterior modificación de los datos deberá seguir las reglas establecidas en la base de datos.

Así, en 'ibb.Cargar_Tablas_Triggers' se almacena el estado actual en que se encuentran los triggers antes de realizar la copia. Posteriormente se deshabilitarán todos aquellos que se encontraban habilitados, se cargarán los datos y se volverán a habilitar los triggers que previamente se encontraban habilitados.

ibb.Cargar_Tablas_ForeingKeys

Tabla creada en la base de datos de destino. Almacena diversa información referente a la Foreing Keys.

Campo Tipo NULL Restricción Descripción
SchemaName_Origen sysname NOT NULL Esquema de la Tabla Origen de la FK
TableName_Origen sysname NOT NULL Nombre de la Tabla Origen de la FK
SchemaTableName_Origen CONCAT(QUOTENAME(SchemaName_Origen), N'.', QUOTENAME(TableName_Origen)) PERSISTED NOT NULL Esquema y Nombre de la Tabla Origen de la FK
SchemaName_Destino sysname NOT NULL Esquema de la Tabla Destino de la FK
TableName_Destino sysname NOT NULL Nombre de la Tabla Destino de la FK
SchemaTableName_Destino CONCAT(QUOTENAME(SchemaName_Destino), N'.', QUOTENAME(TableName_Destino)) PERSISTED NOT NULL Esquema y Nombre de la Tabla Destino de la FK
ForeingKeyName sysname NOT NULL Nombre de la FK
DropForeingKey nvarchar(max) NOT NULL Sentencia para eliminar la FK
DisableForeingKey nvarchar(max) NOT NULL Sentencia para deshabilitar la FK
CreateForeingKey nvarchar(max) NOT NULL Patrón de sentencia para crear la FK
DeleteRecordsForeingKey nvarchar(max) NOT NULL Sentencia para eliminar los registros de la Tabla Origen que impiden levantar la FK
is_not_trusted bit NOT NULL Cargar_Tablas_ForeingKeys_is_not_trusted_DEF DEFAULT (0) sys.foreign_keys
is_disabled bit NOT NULL Cargar_Tablas_ForeingKeys_is_disabled_DEF DEFAULT (0) sys.foreign_keys
Borrada bit NOT NULL Cargar_Tablas_ForeingKeys_Borrada_DEF DEFAULT (0) Flag que indica que la FK ha sido eliminada desde la última vez que se ejecutó Insert Bulk Bestia

Con el fin de poder realizar una copia de datos lo más eficiente y sencillo posible, se eliminan las Foreing Keys (FKs), permitiendo de esta forma la carga "aleatoria" de tablas, es decir, sin tener que seguir un orden lógico de acuerdo a la lógica de negocio.

En esta tabla se almacenan las sentencias para eliminar, deshabilitar y crear las FKs. La sentencia para la creación de las FKs almacenada no es tal, sino un patrón. Los '***' serán sustituidos por WITH NOCHECK o WITH CHECK según indiquen los campos 'is_not_trusted' y/o 'is_disabled'.

El campo 'DeleteRecordsForeingKey' contiene la sentencia a ejecutar para eliminar los registros de la tabla origen que impiden levantar la FK. Esta sentencia se ejecuta si se encuentra marcada la opción 'Eliminar Registros Foreing Keys' del Panel Destino. Si no es así, y existen registros que impiden su levantamiento, la FK no se creará, por lo que la próxima vez que se ejecute Insert Bulk Bestia pondrá en el campo 'Borrada' un 1.

Cuando se ejecuta por segunda vez Insert Bulk Bestia y se encuentra con una FK cuyo campo 'Borrada' tiene el valor 1, la FK ya no se encuentra en la base de datos. Insert Bulk Bestia procederá a su creación ya que no es capaz de determinar si la FK ha sido efectivamente eliminada por el usuario, o bien, no aparece porque en la ejecución anterior no se pudo levantar a causa de la existencia de registros huérfanos.

ibb.Cargar_Tablas_Constraints

Tabla creada en la base de datos de destino. Almacena diversa información referente a las Restricciones.

Campo Tipo NULL Restricción Descripción
SchemaName sysname NOT NULL Esquema de la Tabla de la Restricción
TableName sysname NOT NULL Nombre de la Tabla de la Restricción
SchemaTableName CONCAT(QUOTENAME(SchemaName), N'.', QUOTENAME(TableName)) PERSISTED NOT NULL Esquema y Nombre de la Tabla de la Restricción
ConstraintName sysname NOT NULL Nombre de la Restricción
HabilitaConstraint nvarchar(max) NOT NULL Patrón de la sentencia para habilitar la Restricción
is_not_trusted bit NOT NULL Cargar_Tablas_Constraints_is_not_trusted_DEF DEFAULT (0) sys.check_constraints
is_disabled bit NOT NULL Cargar_Tablas_Constraints_is_disabled_DEF DEFAULT (0) sys.check_constraints
Borrada bit NOT NULL Cargar_Tablas_Constraints_Borrada_DEF DEFAULT (0) Flag que indica que la Restricción ha sido eliminada desde la última vez que se ejecutó Insert Bulk Bestia

Con el fin de poder realizar una copia de datos lo más eficiente posible, se deshabilitan las restricciones.

En esta tabla se almacenan las sentencias para habilitar/deshabilitar las restricciones. La sentencia para la habilitación de las restricciones almacenada no es tal, sino un patrón. Los '***' serán sustituidos por NOCHECK NOCHECK, NOCHECK CHECK o CHECK CHECK según indiquen los campos 'is_not_trusted' y/o 'is_disabled'.

Cuando se ejecuta por segunda vez Insert Bulk Bestia, pondrá en el campo 'Borrada' un 1 a todas aquellas Restricciones que han desaparecido. Como no es capaz de determinar si la Restricción ha sido efectivamente eliminada por el usuario, o bien, no aparece porque en la ejecución anterior no se pudo levantar, Insert Bulk Bestia intentará levantarla.

Además, Insert Bulk Bestia anotará en la tabla ibb.Log_Errores determinados mensajes para aquellas Restricciones que no parecen muy razonables.

ibb.Cargar_Tablas_Indices

Tabla creada en la base de datos de destino. Almacena diversa información referente a los Índices.

Campo Tipo NULL Restricción Descripción
SchemaName sysname NOT NULL Esquema de la Tabla del Índice
TableName sysname NOT NULL Nombre de la Tabla del Índice
SchemaTableName CONCAT(QUOTENAME(SchemaName), N'.', QUOTENAME(TableName)) PERSISTED NOT NULL Esquema y Nombre de la Tabla del Índice
IndexName sysname NOT NULL Nombre del Índice
CreateIndex nvarchar(max) NOT NULL Sentencia para la creación del Índice
DopIndex nvarchar(max) NOT NULL Sentencia para la eliminación del Índice
DeshabilitarIndex nvarchar(max) NOT NULL Sentencia para la deshabilitación de una restricción de tipo Unique.
HabilitarConstraint nvarchar(max) NOT NULL Patrón de sentencia para la habilitación de una restricción de tipo Unique.
RebuildIndex nvarchar(max) NOT NULL Sentencia para la reconstrucción de un Índice.
RebuildAllIndex nvarchar(max) NOT NULL Sentencia para la reconstrucción de todos los Índices de la Tabla.
type tinyint NOT NULL Cargar_Tablas_Indices_type_DEF DEFAULT (0) sys.indexes
type_desc nvarchar(60) NOT NULL Cargar_Tablas_Indices_type_desc_DEF DEFAULT (N'HEAP') sys.indexes
is_primary_key bit NOT NULL Cargar_Tablas_Indices_primary_DEF DEFAULT (0) sys.indexes
is_unique_constraint bit NOT NULL Cargar_Tablas_Indices_unique_constraint_DEF DEFAULT (0) sys.indexes
is_unique bit NOT NULL Cargar_Tablas_Indices_unique_DEF DEFAULT (0) sys.indexes
is_disabled bit NOT NULL Cargar_Tablas_Indices_disabled_DEF DEFAULT (0) sys.indexes
no_recompute bit NOT NULL Cargar_Tablas_Indices_no_recompute_DEF DEFAULT (0) sys.stats
is_tracked_by_cdc bit NOT NULL Cargar_Tablas_Indices_is_tracked_by_cdc_DEF DEFAULT (0) sys.tables
is_tracked_by_ct bit NOT NULL Cargar_Tablas_Indices_is_tracked_by_ct_DEF DEFAULT (0) sys.change_tracking_tables
Borrado bit NOT NULL Cargar_Tablas_Indices_Borrado_DEF DEFAULT (0) Flag que indica que el Índice ha sido eliminado desde la última vez que se ejecutó Insert Bulk Bestia

Con el fin de poder realizar una copia de datos lo más eficiente posible, se eliminan los índices.

En esta tabla se almacenan las sentencias para eliminar y crear índices y restricciones de tipo único.

Cuando se ejecuta por segunda vezInsert Bulk Bestia, pondrá en el campo 'Borrado' un 1 a todos aquellos Índices que han desaparecido. Como no es capaz de determinar si el Índice ha sido efectivamente eliminado por el usuario, o bien, no aparece porque en la ejecución anterior no se pudo crear, Insert Bulk Bestia intentará crear el índice.

Además, Insert Bulk Bestia anotará en la tabla ibb.Log_Errores determinados mensajes para aquellos Índices que están deshabilitados.

Como ya se comentó anteriormente, Insert Bulk Bestia sigue determinada lógica para decidir si un determinado índice debe ser eliminado:

  • No elimina los índices cluster de aquellas tablas en que el campo 'DataKb' de 'ibb.Cargar_Tablas' es mayor que el umbral indicado en 'Tamaño (KB) mínimo para no eliminar índice Cluster' del Panel Carga.
  • Para aquellas tablas que tienen habilitado el seguimiento de cambios por CDC, no elimina ningún índice utilizado por el seguimiento de cambios, ni su índice cluster.
    Seguimiento de cambios CDC: La base de datos tiene en 'sys.databases' el campo 'is_cdc_enabled' a 1 y la tabla tiene en 'sys.tables' el campo 'is_tracked_by_cdc' a 1.
  • Para aquellas tablas que tienen habilitado el seguimiento de cambios por CT, no elimina la Primary Key, ni su índice cluster. Seguimiento de cambios CT: La tabla aparece en 'sys.change_tracking_tables'
  • No elimina ningún índice de aquellas tablas que Insert Bulk Bestia no ha truncado previamente. Insert Bulk Bestia trunca una tabla previamente cuando:
    • Se desean cargar todos los segmentos de la tabla y la tabla no es una tabla optimizada para memoria.
    • Si los segmentos que se desean cargar abarcan todos los registros que contiene la tabla y la tabla no es una tabla optimizada para memoria.

Para la recreación/reconstrucción de los índices, Insert Bulk Bestia dispone de determinadas opciones. Todas ellas se encuentran en el Panel Carga

Usar TEMPDB para Crear Índices

Utilizar la base de datos Tempdb para ordenar los índices cuando se construyen.

Este parámetro, junto con el siguiente, son claves para mejorar la continuidad de los índices, es decir, mejorar las prestaciones finales de la Base de Datos.

Si se marca esta opción, se reduce el tiempo de la construcción de los índices a costa de utilizar espacio en la Base de Datos Tempdb, por lo que ésta debe estar dimensionada de forma adecuada.Además, mejora la continuidad de los mismos.

No se debe marcar esta opción cuando el tamaño de esta base de datos es crítico o es utilizada por otras bases de datos cuyo uso es crítico y no se desea hacer un uso intensivo de esta base de datos.

Creación de Índices con MAXDOP = 0 ó MAXDOP = 1

Utilizar el máximo grado de paralelismo en la creación de índices o serializar dicho proceso.

Si se marca esta opción se reduce el tiempo de la construcción de los índices a costa de utilizar todas las CPU disponibles. Sin embargo, empeora la continuidad de los índices, empeorando las prestaciones finales de la Base de Datos.

Nota: Como alternativa a esta configuración, se recomienda poner este parámetro a False y utilizar la construcción de índices en paralelo. De esta forma, se utilizará cada CPU para construir un sólo índice, pero se construirán en paralelo tantos índices como CPU disponibles en el servidor.

Creación de Índices en Paralelo

Utilizar las librerías integradas en SQL Server deInsert Bulk Bestia para la ejecución de procesos en paralelo. Es posible que determinados tipos de licencia no contemplen esta posibilidad.

Si se marca esta opción se crean los índices en paralelo haciendo un uso muy intensivo de CPU y Discos. En la base de datos de destino se crea el procedimiento almacenado 'ibb.Cargar_Tablas_Create_Index_Paralelo' con el cual se realiza dicho proceso.

El procedimiento almacenado es un ejemplo de cómo utilizar las librerías para la ejecución de sentencias T-SQL en paralelo. En dicho procedimiento almacenado se crea un trabajo que crea los índices de una determinada tabla en un determinado orden, y luego se lanzan en paralelo tantos trabajos como núcleos tenga disponibles la instancia.

NOTA: Si hay algún problema con SQLCLR, como por ejemplo que se quede colgado o entre en un bucle infinito, se puede descargar el AppDomain con:

ALTER ASSEMBLY[SQLServerAsyncExecProcedures] WITH PERMISSION_SET = EXTERNAL_ACCESS
ALTER ASSEMBLY[SQLServerAsyncExecProcedures] WITH PERMISSION_SET = UNSAFE

Un ejemplo puede ser: Nº Error 6522, cuyo mensaje contenga 'SQLServerAsyncExecProcedures.MetodosAuxiliares.TryAcquireLock'. Este error indica que el Diccionario de trabajos a realizar se encuentra bloqueado, por lo que no se puede adquirir un bloqueo.

En el capítulo siguiente se describe en detalle la librería 'SQLServerAsyncExecProcedures' y más adelante se detalla un ejemplo de uso de dichas librerías.