Optimización del rendimiento con índices de almacén de columnas ordenados
Se aplica a: SQL Server 2022 (16.x)
Azure SQL Database
Azure SQL Managed Instance
Base de datos de Azure SQL de Microsoft Fabric
Al habilitar la eliminación eficaz de segmentos, los índices de almacén de columnas ordenados proporcionan un rendimiento más rápido omitiendo grandes cantidades de datos ordenados que no coinciden con el predicado de consulta. Cargar datos en un índice de almacén de columnas ordenado y mantenerlo ordenado a través de recompilaciones de índices puede tardar más tiempo que en un índice no ordenado debido a la operación de ordenación de datos, pero las consultas ordenadas de índices de almacén de columnas se pueden ejecutar más rápido después.
Cuando los usuarios consultan una tabla de almacén de columnas, el optimizador comprueba los valores mínimos y máximos almacenados en cada segmento. Los segmentos que están fuera de los límites del predicado de la consulta no se leen del disco a la memoria. Una consulta puede finalizar más rápido si el número de segmentos que se van a leer y su tamaño total es menor.
Para obtener disponibilidad de índices de almacén de columnas ordenada, consulte Disponibilidad de índice de almacén de columnas ordenada.
Para obtener más información sobre las nuevas características agregadas a los índices columnstore, consulte Novedades en los índices columnstore.
Índice de almacén de columnas ordenado frente a no ordenado
En un índice de almacén de columnas, los datos de cada columna de cada grupo de filas se comprimen en un segmento independiente. Cada segmento contiene metadatos que describen sus valores mínimos y máximos, por lo que los segmentos que están fuera de los límites del predicado de consulta no se leen del disco durante la ejecución de la consulta.
Cuando no se ordena un índice de almacén de columnas, el generador de índices no ordena los datos antes de comprimirlos en segmentos. Esto significa que pueden producirse segmentos con intervalos de valores superpuestos, lo que hace que las consultas lean más segmentos del disco y tarden más tiempo en finalizar.
Al crear un índice de almacén de columnas ordenado, el motor de base de datos ordena los datos existentes por las claves de pedido que especifique antes de que el generador de índices los comprima en segmentos. Con los datos ordenados, la superposición de segmentos se reduce o elimina, lo que permite que las consultas tengan una eliminación de segmentos más eficaz y, por tanto, un rendimiento más rápido porque hay menos segmentos que leer del disco.
Dependiendo de la memoria disponible, el tamaño de los datos, el grado de paralelismo, el tipo de índice (agrupado frente a no agrupado) y el tipo de compilación de índice (sin conexión frente a en línea), la ordenación de los índices de almacén de columnas ordenados podría ser completa (sin superposición de segmentos) o parcial (alguna superposición de segmento). Por ejemplo, la ordenación parcial se produce cuando la memoria disponible no es suficiente para una ordenación completa. Las consultas que usan un índice de almacén de columnas ordenado a menudo se ejecutan más rápido que con un índice no ordenado incluso si el índice ordenado se creó mediante una ordenación parcial.
Se proporciona una ordenación completa para los índices de almacén de columnas agrupados ordenados creados o recompilados con las opciones de ONLINE = ON
y MAXDOP = 1
. En este caso, la ordenación no está limitada por la memoria disponible porque usa la base de datos de tempdb
para desbordar los datos que no caben en la memoria. El proceso de compilación del índice puede ser más lento debido a operaciones adicionales de E/S de tempdb
. Sin embargo, con una recompilación de índices en línea, las consultas pueden seguir usando el índice existente mientras se vuelve a generar el nuevo índice ordenado.
También se puede proporcionar una ordenación completa para los índices de almacén de columnas agrupados y no agrupados ordenados creados o recompilados con las opciones de ONLINE = OFF
y MAXDOP = 1
si la cantidad de datos que se van a ordenar es lo suficientemente pequeña como para ajustarse completamente a la memoria disponible.
En todos los demás casos, la ordenación en los índices de almacén de columnas ordenados es parcial.
Nota
Actualmente, los índices de almacén de columnas ordenados solo se pueden crear o volver a generar en línea en Azure SQL Database y en Azure SQL Managed Instance con la Directiva de actualización siempre actualizada.
Para comprobar los intervalos de segmento de una columna y determinar si hay alguna superposición de segmentos, use la consulta siguiente, sustituyendo los marcadores de posición por los nombres de esquema, tabla y columna:
SELECT OBJECT_SCHEMA_NAME(o.object_id) AS schema_name,
o.name AS table_name,
cols.name AS column_name,
pnp.index_id,
cls.row_count,
pnp.data_compression_desc,
cls.segment_id,
cls.column_id,
cls.min_data_id,
cls.max_data_id
FROM sys.partitions AS pnp
INNER JOIN sys.tables AS t
ON pnp.object_id = t.object_id
INNER JOIN sys.objects AS o
ON t.object_id = o.object_id
INNER JOIN sys.column_store_segments AS cls
ON pnp.partition_id = cls.partition_id
INNER JOIN sys.columns AS cols
ON o.object_id = cols.object_id
AND
cls.column_id = cols.column_id
WHERE OBJECT_SCHEMA_NAME(o.object_id) = '<Schema Name>'
AND
o.name = '<Table Name>'
AND
cols.name = '<Column Name>'
ORDER BY o.name, pnp.index_id, cls.min_data_id;
Por ejemplo, la salida de esta consulta para un índice de almacén de columnas totalmente ordenado podría ser el siguiente. Tenga en cuenta que no hay superposición en las columnas min_data_id
y max_data_id
para distintos segmentos.
schema_name table_name column_name index_id row_count data_compression_desc segment_id column_id min_data_id max_data_id
----------- ---------- ----------- -------- --------- --------------------- ---------- --------- ----------- -----------
dbo Table1 Column1 1 479779 COLUMNSTORE 0 1 -17 1469515
dbo Table1 Column1 1 887658 COLUMNSTORE 1 1 1469516 2188146
dbo Table1 Column1 1 930144 COLUMNSTORE 2 1 2188147 11072928
Nota
En un índice de almacén de columnas ordenado, los nuevos datos resultantes del mismo lote de operaciones de carga de datos o DML se ordenan solo dentro de ese lote. No hay ninguna ordenación global que incluya los datos existentes en la tabla.
Para ordenar los datos en el índice después de insertar nuevos datos o actualizar los datos existentes, vuelva a generar el índice.
Para una recompilación sin conexión de un índice de almacén de columnas con particiones, la recompilación se realiza una partición cada vez. Los datos de la partición que se vuelven a compilar no están disponibles hasta que la recompilación se complete para esa partición.
Los datos permanecen disponibles durante una recompilación en línea. Para obtener más información, consulte Realizar operaciones de índice en línea.
Rendimiento de las consultas
La ganancia de rendimiento de un índice de almacén de columnas ordenado depende de los patrones de consulta, del tamaño de los datos, de la ordenación de los datos, de la estructura física de los segmentos y de los recursos de proceso disponibles para la ejecución de consultas.
Las consultas con los patrones siguientes normalmente se ejecutan más rápido con índices de almacén de columnas ordenados.
- Consultas que tienen predicados de igualdad, desigualdad o rango.
- Consultas en las que las columnas de predicado y las columnas CCI ordenadas son las mismas.
En este ejemplo, la tabla T1
tiene un índice de almacén de columnas agrupado ordenado en la secuencia de Col_C
, Col_B
y Col_A
.
CREATE CLUSTERED COLUMNSTORE INDEX MyOrderedCCI ON T1
ORDER (Col_C, Col_B, Col_A);
El rendimiento de las consultas 1 y 2 puede beneficiarse más del índice columnstore ordenado que las consultas 3 y 4, ya que hacen referencia a todas las columnas ordenadas.
-- query 1
SELECT *
FROM T1
WHERE Col_C = 'c' AND Col_B = 'b' AND Col_A = 'a';
-- query 2
SELECT *
FROM T1
WHERE Col_B = 'b' AND Col_C = 'c' AND Col_A = 'a';
-- query 3
SELECT *
FROM T1
WHERE Col_B = 'b' AND Col_A = 'a';
-- query 4
SELECT *
FROM T1
WHERE Col_A = 'a' AND Col_C = 'c';
Rendimiento de la carga de datos
El rendimiento de la carga de datos en una tabla con un índice de almacén de columnas ordenado es similar a una tabla con particiones. La carga de datos puede tardar más tiempo que con un índice de almacén de columnas no ordenado debido a la operación de ordenación de datos, pero las consultas se pueden ejecutar más rápido después.
Reducción de la superposición de segmentos
El número de segmentos superpuestos depende del tamaño de los datos que se van a ordenar, la memoria disponible y el valor máximo de grado de paralelismo (MAXDOP
) durante la compilación del índice de almacén de columnas ordenado. Las estrategias siguientes reducen la superposición de segmentos, pero pueden hacer que el proceso de compilación del índice tarde más tiempo.
- Si la compilación de índices en línea está disponible, use las opciones
ONLINE = ON
yMAXDOP = 1
al crear un índice de almacén de columnas agrupado ordenado. Esto crea un índice totalmente ordenado. - Si la compilación de índices en línea no está disponible, use la opción
MAXDOP = 1
. - Ordene previamente los datos por las claves de ordenación antes de la carga.
Cuando MAXDOP
es mayor que 1, cada subproceso utilizado para la creación del índice de almacén de columnas ordenado trabaja en un subconjunto de datos y lo ordena localmente. No hay ninguna ordenación global entre los datos ordenados por subprocesos diferentes. El uso de subprocesos paralelos puede reducir el tiempo de creación del índice, pero genera más segmentos superpuestos que cuando se usa un único subproceso. El uso de una operación de un solo hilo ofrece la máxima calidad de compresión. Puede especificar MAXDOP
con el comando CREATE INDEX
.
Ejemplos
Buscar columnas ordenadas y ordinal
SELECT object_name(c.object_id) AS table_name,
c.name AS column_name,
i.column_store_order_ordinal
FROM sys.index_columns AS i
INNER JOIN sys.columns AS c
ON i.object_id = c.object_id
AND
c.column_id = i.column_id
WHERE column_store_order_ordinal <> 0;
Creación de un índice de almacén de columnas ordenado
Índice de almacén de columnas ordenado agrupado:
CREATE CLUSTERED COLUMNSTORE INDEX OCCI
ON dbo.Table1
ORDER (Column1, Column2);
Índice de almacén de columnas ordenado no agrupado:
CREATE NONCLUSTERED COLUMNSTORE INDEX ONCCI
ON dbo.Table1
(
Column1, Column2, Column3
)
ORDER (Column1, Column2);
Agregar o quitar columnas de pedido y recompilar un índice de almacén de columnas ordenado existente
Índice de almacén de columnas ordenado agrupado:
CREATE CLUSTERED COLUMNSTORE INDEX OCCI
ON dbo.Table1
ORDER (Column1, Column2)
WITH (DROP_EXISTING = ON);
Índice de almacén de columnas ordenado no agrupado:
CREATE NONCLUSTERED COLUMNSTORE INDEX ONCCI
ON dbo.Table1
(
Column1, Column2, Column3
)
ORDER (Column1, Column2)
WITH (DROP_EXISTING = ON);
Creación de un índice de almacén de columnas agrupado ordenado en línea con ordenación completa en una tabla de montón
CREATE CLUSTERED COLUMNSTORE INDEX OCCI
ON dbo.Table1
ORDER (Column1)
WITH (ONLINE = ON, MAXDOP = 1);
Recompilación de un índice de almacén de columnas agrupado ordenado en línea con una ordenación completa
CREATE CLUSTERED COLUMNSTORE INDEX OCCI
ON dbo.Table1
ORDER (Column1)
WITH (DROP_EXISTING = ON, ONLINE = ON, MAXDOP = 1);
Contenido relacionado
- Directrices de diseño del índice Columnstore
- Índices de Columnstore: guía de carga de datos
- Introducción a los índices de almacén de columnas para el análisis operativo en tiempo real
- Índices de almacén de columnas de almacenamiento de datos
- Optimización del mantenimiento de índices para mejorar el rendimiento de las consultas y reducir el consumo de recursos
- Arquitectura de índices de almacén de columnas
- CREATE INDEX (Transact-SQL)
- ALTER INDEX (Transact-SQL)