Tarea
Archive todos menos un período continuo de 13 meses de un grupo de tablas grandes. Los datos archivados deben almacenarse en otra base de datos.
- La base de datos está en modo de recuperación simple.
- Las tablas son de 50 mil filas a varios miles de millones y en algunos casos ocupan cientos de gb cada una.
- Las tablas actualmente no están particionadas
- Cada tabla tiene un índice agrupado en una columna de fecha cada vez mayor
- Cada tabla además tiene un índice no agrupado
- Todos los cambios de datos en las tablas son inserciones
- El objetivo es minimizar el tiempo de inactividad de la base de datos primaria.
- El servidor es 2008 R2 Enterprise
La tabla "archivo" tendrá alrededor de 1.100 millones de filas, la tabla "en vivo" unos 400 millones. Obviamente, la tabla de archivo aumentará con el tiempo, pero espero que la tabla en vivo también aumente razonablemente rápido. Digamos 50% en los próximos dos años al menos.
Pensé en las bases de datos estiradas de Azure, pero desafortunadamente estamos en 2008 R2 y es probable que nos quedemos allí por un tiempo.
Plan actual
- Crea una nueva base de datos
- Cree nuevas tablas particionadas por mes (usando la fecha de modificación) en la nueva base de datos.
- Mueva los últimos 12-13 meses de datos a las tablas particionadas.
- Realice un cambio de nombre de las dos bases de datos
- Elimine los datos movidos de la base de datos ahora "archivada".
- Particionar cada una de las tablas en la base de datos "archivo".
- Use intercambios de partición para archivar los datos en el futuro.
- Me doy cuenta de que tendré que cambiar los datos a archivar, copiar esa tabla en la base de datos de archivo y luego cambiarla a la tabla de archivo. Esto es aceptable
Problema: estoy tratando de mover los datos a las tablas particionadas iniciales (de hecho, todavía estoy haciendo una prueba de concepto). Estoy tratando de usar TF 610 (según la Guía de rendimiento de carga de datos ) y una INSERT...SELECT
declaración para mover los datos inicialmente pensando que se registraría mínimamente. Lamentablemente, cada vez que lo intento está completamente registrado.
En este punto, creo que mi mejor opción puede ser mover los datos usando un paquete SSIS. Estoy tratando de evitar eso, ya que estoy trabajando con 200 tablas y todo lo que puedo hacer por script lo puedo generar y ejecutar fácilmente.
¿Hay algo que me falta en mi plan general, y es SSIS mi mejor apuesta para mover los datos rápidamente y con un uso mínimo del registro (preocupaciones de espacio)?
Código de demostración sin datos
-- Existing structure
USE [Audit]
GO
CREATE TABLE [dbo].[AuditTable](
[Col1] [bigint] NULL,
[Col2] [int] NULL,
[Col3] [int] NULL,
[Col4] [int] NULL,
[Col5] [int] NULL,
[Col6] [money] NULL,
[Modified] [datetime] NULL,
[ModifiedBy] [varchar](50) NULL,
[ModifiedType] [char](1) NULL
);
-- ~1.4 bill rows, ~20% in the last year
CREATE CLUSTERED INDEX [AuditTable_Modified] ON [dbo].[AuditTable]
( [Modified] ASC )
GO
-- New DB & Code
USE Audit_New
GO
CREATE PARTITION FUNCTION ThirteenMonthPartFunction (datetime)
AS RANGE RIGHT FOR VALUES ('20150701', '20150801', '20150901', '20151001', '20151101', '20151201',
'20160101', '20160201', '20160301', '20160401', '20160501', '20160601',
'20160701')
CREATE PARTITION SCHEME ThirteenMonthPartScheme AS PARTITION ThirteenMonthPartFunction
ALL TO ( [PRIMARY] );
CREATE TABLE [dbo].[AuditTable](
[Col1] [bigint] NULL,
[Col2] [int] NULL,
[Col3] [int] NULL,
[Col4] [int] NULL,
[Col5] [int] NULL,
[Col6] [money] NULL,
[Modified] [datetime] NULL,
[ModifiedBy] [varchar](50) NULL,
[ModifiedType] [char](1) NULL
) ON ThirteenMonthPartScheme (Modified)
GO
CREATE CLUSTERED INDEX [AuditTable_Modified] ON [dbo].[AuditTable]
(
[Modified] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON ThirteenMonthPartScheme (Modified)
GO
CREATE NONCLUSTERED INDEX [AuditTable_Col1_Col2_Col3_Col4_Modified] ON [dbo].[AuditTable]
(
[Col1] ASC,
[Col2] ASC,
[Col3] ASC,
[Col4] ASC,
[Modified] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON ThirteenMonthPartScheme (Modified)
GO
Mover código
USE Audit_New
GO
DBCC TRACEON(610);
INSERT INTO AuditTable
SELECT * FROM Audit.dbo.AuditTable
WHERE Modified >= '6/1/2015'
ORDER BY Modified
fuente
Respuestas:
¿Por qué no obtiene un registro mínimo?
He encontrado que la Guía de rendimiento de carga de datos , a la que hace referencia, es un recurso extremadamente valioso. Sin embargo, tampoco es 100% completo, y sospecho que la cuadrícula ya es lo suficientemente compleja como para que el autor no haya agregado una columna
Table Partitioning
para separar las diferencias de comportamiento dependiendo de si la tabla que recibe las inserciones está particionada. Como veremos más adelante, el hecho de que la tabla ya esté particionada parece inhibir el registro mínimo.Enfoque recomendado
Según las recomendaciones de la Guía de rendimiento de carga de datos (incluida la sección "Carga masiva de una tabla particionada"), así como una amplia experiencia en la carga de tablas particionadas con decenas de miles de millones de filas, este es el enfoque que recomendaría:
Las diferencias en comparación con su enfoque original:
TABLOCK
un mes a la vez, utilizando el cambio de partición para colocar los datos en la tabla particionada.DELETE
para borrar la tabla anterior se registrará completamente. Tal vez puedaTRUNCATE
o soltar la tabla y crear una nueva tabla de archivo.Comparación de enfoques para mover el año reciente de datos
Para comparar enfoques en un tiempo razonable en mi máquina, utilicé un
100MM row
conjunto de datos de prueba que generé y que sigue su esquema.Como puede ver en los resultados a continuación, hay un gran aumento y reducción del rendimiento en las escrituras de registros al cargar datos en un montón utilizando la
TABLOCK
sugerencia. Hay un beneficio adicional si se hace una partición a la vez. También vale la pena señalar que el método de una partición a la vez se puede paralelizar fácilmente si ejecuta múltiples particiones a la vez. Dependiendo de su hardware, eso podría dar un buen impulso; Por lo general, cargamos al menos cuatro particiones a la vez en hardware de clase de servidor.Aquí está el script de prueba completo .
Notas finales
Todos estos resultados dependen de su hardware hasta cierto punto. Sin embargo, mis pruebas se realizaron en una computadora portátil estándar de cuatro núcleos con unidad de disco giratoria. Es probable que las cargas de datos sean mucho más rápidas si está utilizando un servidor decente que no tiene mucha otra carga en el momento en que realiza este proceso.
Por ejemplo, ejecuté el enfoque recomendado en un servidor de desarrollo real (Dell R720) y vi una reducción a
76 seconds
(desde156 seconds
mi computadora portátil). Curiosamente, el enfoque original de insertar en una tabla particionada no experimentó la misma mejora y aún se hizo cargo12 minutes
del servidor de desarrollo. Presumiblemente esto se debe a que este patrón produce un plan de ejecución en serie, y un único procesador en mi computadora portátil puede coincidir con un único procesador en el servidor de desarrollo.fuente
Este puede ser un buen candidato para Biml. Un enfoque sería crear una plantilla reutilizable que migrara datos para una sola tabla en pequeños intervalos de fechas con un contenedor Para cada. Biml recorrerá su colección de tablas para crear paquetes idénticos para cada tabla calificada. Andy Leonard tiene una introducción en su serie de escaleras .
fuente
Tal vez, en lugar de crear la nueva base de datos, restaure la base de datos real a una nueva base de datos y elimine los datos más recientes de 12 a 13 meses. Luego, en su base de datos real, elimine los datos que no están contenidos en su área de archivo recién creada. Si las eliminaciones grandes son un problema, tal vez solo pueda eliminar conjuntos de 10K o más grandes a modo de script para hacerlo.
Sus tareas de particionamiento no parecen interferir y parecen ser aplicables a cualquiera de las bases de datos después de las eliminaciones.
fuente