Cómo particionar una tabla no particionada existente

22

Tengo una tabla existente con datos:

dbo.Test (col1,col2,col3....) ON [PRIMARY]

Necesito cambiar esta tabla para particionarla así:

dbo.Test(col1,col2,col3....) ON Ps_Date(Col2)

¿Cómo puedo lograr esto sin dejar caer y volver a crear la mesa?

343
fuente

Respuestas:

23

Para particionar una tabla, puede seguir los siguientes pasos breves:

  • primero cree una función de partición y un esquema de partición
  • Después de eso, puede particionar una tabla.
  • SI su tabla tiene un índice agrupado, entonces debe soltarlo y DROP_EXISTINGvolver a crearlo en la partición correcta o puede usar la cláusula para volver a crear el índice agrupado.
  • Si su tabla no tiene un índice agrupado, puede crear uno en la partición correcta utilizando el esquema de partición.
  • Además, Enterprise Edition tiene la flexibilidad de usar la ONLINE=ONopción de la instrucción CREATE INDEX para minimizar cualquier tiempo de inactividad para su aplicación. Tenga en cuenta que verá una degradación del rendimiento mientras se reconstruye el índice con la opción EN LÍNEA.

Para automatizar el particionamiento, puede usar la utilidad de administración de particiones de SQL Server o el marco de tablas particionadas de SQL Server disponible también en codeplex.

Algunos buenos recursos:

Kin Shah
fuente
53

No especifica si su tabla tiene un índice agrupado o no, así que veamos todas las opciones.

Voy a usar este ejemplo de función de partición, esquema de partición y tabla:

CREATE PARTITION FUNCTION pf1(INT) AS RANGE LEFT FOR VALUES(10,20,30,40);
GO
CREATE PARTITION SCHEME ps1 AS PARTITION pf1 ALL TO ([PRIMARY])
GO
CREATE TABLE dbo.pt(pc INT NOT NULL, id INT NOT NULL) ON [PRIMARY];
GO

1. Su tabla tiene un índice agrupado que no fue creado por una restricción.

Este es el caso más fácil. Puede usar la CREATE INDEXdeclaración con la DROP_EXISTINGcláusula para mover la tabla al esquema de partición.

Supongamos, por ejemplo, que este índice agrupado se ha creado:

CREATE UNIQUE CLUSTERED INDEX ptc ON dbo.pt(Id) ON [PRIMARY];

Para particionar esta tabla, el índice agrupado ha incluido la columna de partición (pt en nuestro caso) como parte de la clave. Esta declaración cambia el índice agrupado para incluir la columna de partición y la divide al mismo tiempo:

CREATE UNIQUE CLUSTERED INDEX ptc ON dbo.pt(pc, Id) WITH(DROP_EXISTING = ON)ON ps1(pc) ;

La DROP_Existingcláusula elimina automáticamente el índice existente antes de crear el nuevo. Esto es preferible a un separado DROP INDEXya que hace que los índices no agrupados se reconstruyan solo una vez.

2. Su tabla tiene un índice agrupado que es parte de una restricción PRIMARY KEYo UNIQUEcontiene la columna de partición como parte de la clave

Este sigue siendo fácil y muy similar al anterior.

Suponga que esta PRIMARY KEYrestricción se ha creado en la tabla:

ALTER TABLE dbo.pt ADD CONSTRAINT ptc PRIMARY KEY CLUSTERED (pc, Id) ON [PRIMARY];

Ahora puede ejecutar el mismo script de recreación que usamos en 1:

CREATE UNIQUE CLUSTERED INDEX ptc ON dbo.pt(pc, Id) WITH(DROP_EXISTING = ON)ON ps1(pc) ;

3. La tabla tiene un índice agrupado que no incluye la columna de la partición, pero se creó como parte de una PRIMARY KEYo UNIQUErestricción

Mala suerte No puede cambiar la definición de a PRIMARY KEYo UNIQUErestricción después del hecho. Su única opción es eliminar la restricción y luego volver a crearla, incluida la columna de partición, o crear un índice agrupado independiente de la restricción que incluye la columna de partición. En el segundo caso, puede volver a crear la restricción NONCLUSTEREDsin incluir la columna de partición. Debido a que ahora esta restricción no está alineada (lo que significa que su índice de soporte no está particionado), debe especificar dónde colocarla en el disco.

Suponga que la tabla tenía una clave primaria como esta:

ALTER TABLE dbo.pt ADD CONSTRAINT ptc PRIMARY KEY CLUSTERED (Id) ON [PRIMARY];

Para particionar esta tabla, primero debe eliminar la restricción:

ALTER TABLE dbo.pt DROP CONSTRAINT ptc;

Luego debe crear el índice agrupado particionado:

CREATE UNIQUE CLUSTERED INDEX ptci ON dbo.pt(pc, Id) ON ps1(pc) ;

Si elige volver a crear la PRIMARY KEYrestricción no alineada, puede hacerlo así:

ALTER TABLE dbo.pt ADD CONSTRAINT ptc PRIMARY KEY NONCLUSTERED (Id) ON [PRIMARY];

4. Su tabla no tiene un índice agrupado

En este caso, se recomienda en la mayoría de los casos simplemente crear un índice agrupado para establecer la partición. Puede usar la declaración de índice de creación vista anteriormente para eso:

CREATE UNIQUE CLUSTERED INDEX ptci ON dbo.pt(pc, Id) ON ps1(pc) ;

Sin embargo, si tiene una buena razón para no crear un índice agrupado, puede salirse con la suya con el siguiente enfoque de dos pasos. Lamentablemente, no hay una forma directa de hacer este cambio.

Suponga que su tabla no tiene un índice agrupado. Para particionar la tabla, primero debe crear una CLUSTERED UNIQUErestricción. (También podría usar una CLUSTERED PRIMARY KEYrestricción). Si tiene una combinación de columnas que es única, ese es un paso simple:

ALTER TABLE dbo.pt ADD CONSTRAINT ptc UNIQUE CLUSTERED(pc,id);

Después de crear la restricción, puede soltarla nuevamente y "mover" la tabla al nuevo esquema de partición al mismo tiempo:

ALTER TABLE dbo.pt DROP CONSTRAINT ptc WITH(MOVE TO ps1(pc));

Si no tiene una combinación de columnas que sea única, no tiene suerte. En este caso, su única opción es agregar una nueva columna y llenarla con valores únicos. Si la tabla es razonablemente pequeña, puede hacer algo como esto:

ALTER TABLE dbo.pt ADD tmp_id INT IDENTITY(1,1);

Sin embargo, eso tomará un bloqueo de tabla exclusivo hasta que se valoren todas las filas. Dependiendo del tamaño de la mesa, esto puede ser durante bastante tiempo. Después de crear esa columna, siga los dos pasos anteriores para crear primero la UNIQUErestricción y luego soltarla nuevamente de inmediato. Después, también puede soltar la columna nuevamente. Todos estos pasos son bastante intrusivos, por lo que probablemente sea mejor simplemente crear un índice agrupado en la tabla. Eso ni siquiera tiene que ser único.


Si tiene Enterprise Edition, puede usar la WITH(ONLINE=ON)cláusula en la mayoría de las declaraciones anteriores. Eso mantendrá su mesa disponible para otras conexiones. Sin embargo, habrá un impacto en el rendimiento durante ese tiempo.

Sebastian Meine
fuente
1
¡Excelente, Sabastian! Simplemente excelente! Solo para agregar al # 3 anterior ... si desea usar SWITCH dentro o fuera, todos los índices deben estar alineados. Hacer un PK no agrupado y no alineado no le permitirá hacer un INTERRUPTOR a menos que primero realice los pasos para soltar el índice, haga el INTERRUPTOR (en cualquier dirección) y reconstruya el índice. Eso a menudo es aún más rápido que hacer el equivalente con eliminaciones y, por supuesto, si no necesita usar SWITCH, no será un problema.
Jeff Moden