Cómo crear un índice agrupado en una tabla de 100 GB

8

Tengo una tabla de almacenamiento dinámico que ocupa alrededor de 104 GB de espacio en disco con casi 3 mil millones de filas. Estoy tratando de crear un índice agrupado en esta tabla en la WeekEndingDatecolumna [ ]. Tengo alrededor de 200 gb's gratis en el archivo de datos y alrededor de 280 gb's gratis en el tempdb.

He intentado dos métodos diferentes. Primero fue crear el índice directamente en la tabla con el siguiente comando:

CREATE CLUSTERED INDEX CX_WT_FOLD_HISTORY
ON WT_FOLD_HISTORY (WeekEndingDate ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = ON, 
IGNORE_DUP_KEY = OFF
, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, 
DATA_COMPRESSION = PAGE)

Lo intenté con SORT_IN_TEMPDB = ONy OFF. Al usarlo ON, llenaba el tempdb y con OFFél llenaba la unidad de datos.

Otro método era crear una nueva tabla en blanco con el índice necesario y luego insertar los registros del montón en la nueva tabla. Esto también falló después de llenar la unidad de datos.

Cualquier otra sugerencia sobre qué hacer. La mayoría de las cosas que he leído indican que necesitaría aproximadamente 1,2 veces el tamaño de la tabla para usarla como espacio de trabajo al crear el índice. Tengo mucho más que eso y todavía falla. Cualquier sugerencia sera apreciada.

Aquí está mi estructura de tabla de montón original:

CREATE TABLE [dbo].[WT_FOLD_HISTORY](
[WeekEndingDate] [varchar](50) NULL,
[Division] [varchar](50) NULL,
[Store] [varchar](50) NULL,
[SKUNumber] [varchar](50) NULL,
[UPC] [varchar](50) NULL,
[SalesUnits] [varchar](50) NULL,
[SalesCost] [varchar](50) NULL,
[SalesRetail] [varchar](50) NULL,
[InventoryUnits] [varchar](50) NULL,
[InventoryCost] [varchar](50) NULL,
[InventoryRetail] [varchar](50) NULL,
[OnOrderUnits] [varchar](50) NULL,
[OnOrderCost] [varchar](50) NULL,
[OnOrderRetail] [varchar](50) NULL,
[ReceiptUnits] [varchar](50) NULL,
[ReceiptCost] [varchar](50) NULL,
[ReceiptRetail] [varchar](50) NULL,
[PermanentMarkdowns] [varchar](50) NULL,
[ReturnsToVendor] [varchar](50) NULL,
[POSMarkdowns] [varchar](50) NULL,
[TimeFK] [smallint] NULL,
[LocationFK] [int] NULL,
[ItemFK] [int] NULL
) ON [AcademySports_DataFG1]
user578849
fuente
Al hacer el enfoque de "nueva tabla, mover filas en lotes", ¿está eliminando filas en la tabla original a medida que las mueve? Es posible que deba hacer algo de gimnasia adicional para obtener el montón para liberar el espacio no utilizado a medida que elimina datos.
AMtwo
Puede ser interesante saber por qué un índice no agrupado no es aceptable en este caso; [sí, soy consciente de las diferencias / beneficios de agrupados versus no agrupados ... solo tengo curiosidad por saber por qué ha descartado un índice no agrupado]; Además, ¿la tabla ya tiene índices no agrupados y, en caso afirmativo, cuánto espacio utilizan? [preguntándose si la caída de cualquier índice actual no agrupado podría liberar suficiente espacio para crear el índice agrupado?]
markp-fuso
¿Has intentado crear el índice con DATA_COMPRESSION=NONE? Si eso funciona, podría comprimir después.
Dan Guzman
buena pregunta.i busco en Google y lea esto es lo que dijeron dba.stackexchange.com/questions/11956/… o stackoverflow.com/questions/2309889/… Esta es la única respuesta correcta.
KumarHarsh
1
Solo para estar seguro, ¿podría incluir el mensaje de error real con el que falla?
RDFozz

Respuestas:

3

Si tiene una necesidad a corto plazo de espacio en disco, una opción sería:

  1. Reduce temporalmente tempdb, liberando tanto espacio en esa unidad como parece seguro.
  2. Cree un archivo de datos secundario para el DB en el que se encuentra la tabla en la unidad tempdb.
  3. Agregue el índice agrupado a la tabla.
  4. Reduzca el archivo secundario migrando todos los datos fuera de él.
  5. Eliminar el archivo secundario.
  6. Asegúrese de que el archivo tempdb pueda crecer hasta su tamaño anterior.
  7. Reconstruir índices en la base de datos de la tabla (la eliminación del archivo secundario habrá causado cierta fragmentación).

NOTA: como otros han sugerido, solo haría esto después de cosas como eliminar temporalmente los índices no agrupados de la tabla en cuestión. Esto en particular permitirá que la adición del índice agrupado vaya más rápido, ya que los índices no agrupados tendrían que reconstruirse de todos modos (con un índice agrupado en su lugar, la clave de índice se usa para ubicar las filas en la tabla misma) .

Ese es en realidad otro punto: ¿qué tan ancha es la clave en el índice agrupado? Si tiene índices no agrupados, y la clave en el índice agrupado es significativamente más ancha que el puntero en el montón, entonces los índices no agrupados consumirán más espacio después de crear el índice agrupado.

Si la clave del clúster consta de varias columnas, o incluso una columna grande (por ejemplo, una varcharcolumna con una longitud promedio de 25 o más), es posible que desee considerar una clave sustituta en su lugar (generalmente un valor monotónicamente creciente, para un mejor INSERTrendimiento.

RDFozz
fuente
1

Lo que está llenando su espacio es su megaclasificación (intenta ordenar todos sus 104Gb en conjunto), por lo que creo que se puede resolver haciendo la clasificación en porciones más pequeñas. Le sugiero que cree la nueva tabla agrupada e inserte los datos en pequeños fragmentos como este:

declare @rowcount int = 1;
while @rowcount > 0
begin
  delete top (5000) 
  from your_heap with(tablock) 
      output deleted.field1, ..., deleted.fieldN 
      into new_clustered_table;
  set @rowcount = @@rowcount;
end; 

De esta forma, solo ordena 5000 filas a la vez y el único problema son las divisiones de página que no se pueden evitar ya que no realiza una inserción ordenada. Entonces, cuando termine, new_clustered_table se fragmentará pero puede reconstruirlo después.

sepupic
fuente
Sí, tienes razón, actualicé mi respuesta, pero fue solo una idea.
Sepupic
0

Solo un consejo rápido: considere eliminar todos los índices no agrupados (si los hay) en este montón antes de intentar crear el Índice agrupado. Puede crear un script para aquellos que no son CI junto con sus detalles de columnas de inclusión y crearlos más tarde con esas definiciones después de que el Índice agrupado se haya creado correctamente.

Channdeep Singh
fuente