¿Cuál es la mejor manera de archivar todo menos el año actual y particionar la tabla al mismo tiempo?


23

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...SELECTdeclaració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

RE "mover los datos": para minimizar el uso del registro, puede mover los datos en lotes, por ejemplo, "Aprobar 2" en dba.stackexchange.com/a/139009/94130 . Sobre el tema de la partición, ¿ha considerado las vistas particionadas?
Alex

@ Alex Sí, he considerado ambos. Mi plan de respaldo es mover los datos en lotes usando SSIS. Y para este caso particular, mi problema es exactamente para qué se crea la partición. (carga / descarga rápida de datos mediante conmutación)
Kenneth Fisher

Respuestas:


10

¿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 Partitioningpara 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.

ingrese la descripción de la imagen aquí

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:

  • Crea una nueva base de datos.
  • Cree nuevas tablas particionadas por mes en la nueva base de datos.
  • Mueva el año de datos más reciente, de la siguiente manera:
    • Para cada mes, cree una nueva tabla de montón;
    • Inserte ese mes de datos en el montón utilizando la sugerencia TABLOCK;
    • Agregue el índice agrupado al montón que contiene ese mes de datos;
    • Agregue la restricción de verificación que exige que la tabla contenga solo los datos de este mes;
    • Cambie la tabla a la partición correspondiente de la nueva tabla particionada general.
  • Realice un cambio de nombre de las dos bases de datos.
  • Truncar los datos en la base de datos ahora "archivo".
  • Particionar cada una de las tablas en la base de datos "archivo".
  • Use intercambios de partición para archivar los datos en el futuro.

Las diferencias en comparación con su enfoque original:

  • La metodología de mover los últimos 12-13 meses de datos será mucho más eficiente si carga en un montón con TABLOCKun mes a la vez, utilizando el cambio de partición para colocar los datos en la tabla particionada.
  • A DELETEpara borrar la tabla anterior se registrará completamente. Tal vez pueda TRUNCATEo 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 rowconjunto 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 TABLOCKsugerencia. 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.

ingrese la descripción de la imagen aquí

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(desde 156 secondsmi computadora portátil). Curiosamente, el enfoque original de insertar en una tabla particionada no experimentó la misma mejora y aún se hizo cargo 12 minutesdel 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.


Gracias de nuevo Geoff. Estoy usando el método SWITCH. Específicamente estoy usando SSIS y SQL dinámico para ejecutar los 13 meses en paralelo.
Kenneth Fisher

1

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 .


0

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.


Lo he hecho con bases de datos más pequeñas antes. Dado el tamaño actual y el hecho de que quiero terminar con tablas particionadas en ambos lados, creo que este método realmente tomaría más tiempo y un poco más de espacio (el doble del tamaño actual de la base de datos en min)
Kenneth Fisher
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.