Todos los productos
Search
Centro de documentos

PolarDB:Configurar claves de ordenamiento para índices columnstore

Última actualización: Sep 05, 2026

Los datos de un índice columnstore se escriben físicamente en el orden de la clave primaria. En el caso de las filas actualizadas, se escriben al final del archivo. Por lo tanto, los datos suelen estar desordenados. Sin un orden definido, el pruner de In-Memory Column Index (IMCI) lee más bloques de datos de columna de los necesarios para resolver una consulta. Las claves de ordenamiento le permiten controlar el orden físico de estos bloques. Así, el pruner omite los bloques irrelevantes y reduce las operaciones de E/S.

Cómo funciona

Los datos de un índice columnstore se organizan en grupos de 64,000 filas cada uno. Dentro de cada grupo, las columnas se empaquetan en bloques de datos de columna. Cada bloque almacena los valores mínimo y máximo de sus datos como metadatos, que funcionan como un índice aproximado. Cuando se ejecuta una consulta, el pruner de IMCI clasifica todos los bloques de datos de columna en tres categorías según el predicado de la consulta y estos metadatos:

  • Relevantes: deben leerse.

  • Posiblemente relevantes: se leen como candidatos.

  • Irrelevantes: se omiten por completo.

El orden físico de los bloques de datos de columna determina la eficacia de esta eliminación. Para una consulta como SELECT * FROM t WHERE c >= 8, un conjunto de bloques desordenado obliga a cargarlos todos. Un conjunto ordenado permite que el pruner omita cualquier bloque cuyo valor máximo sea menor que 8.

Columnstore index resorting

Cuándo usar claves de ordenamiento

Las claves de ordenamiento son más eficaces cuando:

  • La tabla es grande (cientos de gigabytes o más).

  • Las consultas son selectivas, es decir, filtran un subconjunto pequeño de filas en lugar de examinar toda la tabla.

  • Un porcentaje alto de las consultas utiliza las mismas columnas de filtro.

Las claves de ordenamiento resultan menos útiles cuando:

  • Las consultas examinan la mayor parte de la tabla sin filtros selectivos.

  • El throughput de escritura es más importante que el rendimiento de lectura. El ordenamiento incremental se ralentiza cuando la carga de trabajo de escritura es alta para liberar recursos destinados a dichas operaciones.

  • El tiempo de compilación está limitado. El ordenamiento aumenta significativamente el tiempo de compilación del índice (consulte Referencia de rendimiento).

Requisitos previos

Antes de empezar, asegúrese de contar con lo siguiente:

  • Un clúster de PolarDB for MySQL Enterprise Edition en una de las siguientes versiones:

    Ordenamiento de datos al crear un nuevo índice columnstore:

    Versión

    Revisión mínima

    PolarDB for MySQL 8.0.1

    8.0.1.1.32

    PolarDB for MySQL 8.0.2

    8.0.2.2.12

    Ordenamiento incremental:

    Versión

    Revisión mínima

    PolarDB for MySQL 8.0.1

    8.0.1.1.39.1

    PolarDB for MySQL 8.0.2

    8.0.2.2.20.1

Para comprobar la versión de su clúster, consulte Query the version number.

Limitaciones

  • Las columnas BLOB, JSON y GEOMETRY no se pueden usar como claves de ordenamiento.

  • El ordenamiento incremental no admite columnas de enteros sin signo ni Decimal como claves de ordenamiento.

  • El ordenamiento incremental mantiene el orden únicamente con base en la primera columna de la clave de ordenamiento. Las columnas adicionales de la clave no se mantienen de forma incremental.

  • Cuando la carga de trabajo de escritura es alta, el ordenamiento incremental se ralentiza para liberar recursos destinados a las operaciones de escritura.

Elegir las columnas de la clave de ordenamiento

Elegir las columnas adecuadas determina qué tanta ventaja obtendrá del pruning. Siga estas recomendaciones:

  1. Dé prioridad a las columnas que se usan en filtros de rango o de igualdad. Estas aprovechan mejor el pruning de mínimos y máximos. Para consultas de rango de fechas (por ejemplo, WHERE order_date BETWEEN ... AND ...), la columna de fecha es una excelente candidata.

  2. Prefiera columnas de baja cardinalidad como clave principal. El pruner omite bloques de manera más eficaz cuando la primera columna de la clave de ordenamiento tiene una cardinalidad relativamente baja. Una columna con una cardinalidad muy alta (por ejemplo, un ID de usuario único) genera bloques con rangos de mínimos y máximos amplios, lo que reduce la eficacia de la omisión.

  3. Agregue columnas de predicados de unión como claves secundarias si aún cuenta con capacidad disponible.

  4. Limite la cantidad de columnas en la clave de ordenamiento. Agregar más columnas incrementa el tiempo de compilación, mientras que la ventaja del pruning disminuye progresivamente.

Configurar claves de ordenamiento

Paso 1: Habilitar el ordenamiento de datos

Establezca el parámetro imci_enable_pack_order_key en ON.

Este parámetro tiene el valor ON de forma predeterminada. Si no lo ha modificado, el ordenamiento ya está activo para los nuevos índices columnstore que se creen.

Para conocer las diferencias en los nombres de los parámetros entre la consola de PolarDB y una sesión de base de datos, consulte Parámetros.

Paso 2: Agregar claves de ordenamiento a la tabla

Ejecute la siguiente instrucción para especificar las columnas de la clave de ordenamiento:

ALTER TABLE table_name COMMENT 'columnar=1 order_key=column_name[,column_name]';

Parámetro

Descripción

table_name

El nombre de la tabla.

column_name

La columna que se usará como clave de ordenamiento. Separe varias columnas con comas.

Ejemplo: ordene la tabla lineitem por fecha de recepción y modo de envío:

ALTER TABLE lineitem COMMENT='columnar=1 order_key=l_receiptdate,l_shipmode';

Paso 3: Supervisar el progreso de compilación

Consulte INFORMATION_SCHEMA.IMCI_ASYNC_DDL_STATS para dar seguimiento al progreso de compilación:

SELECT * FROM INFORMATION_SCHEMA.IMCI_ASYNC_DDL_STATS;

Para consultar la descripción de las columnas, vea View DDL execution speed and build progress for IMCIs.

Parámetros

Para habilitar o deshabilitar el ordenamiento y configurar el paralelismo, establezca los siguientes parámetros en su clúster.

Los nombres de los parámetros difieren entre la consola de PolarDB y una sesión de base de datos.
PolarDB console: Utilice los nombres de los parámetros con el prefijo loose_ (por ejemplo, loose_imci_enable_pack_order_key ). La consola agrega este prefijo para mantener la compatibilidad con el archivo de configuración de MySQL.
Sesión de base de datos (cliente SQL o línea de comandos): Quite el prefijo loose_ y utilice el nombre base del parámetro (por ejemplo, imci_enable_pack_order_key ).
ParámetroDescripciónPredeterminado
loose_imci_enable_pack_order_keyControla si se ordenan los datos al crear un nuevo índice columnstore. Establézcalo en ON para habilitarlo o en OFF para deshabilitarlo.ON
loose_imci_enable_pack_order_key_changed_rebuildControla si se recompila la tabla cuando cambia el orden de clasificación. Establézcalo en ON para exigir la recompilación o en OFF para omitirla.OFF
loose_imci_parallel_build_threads_per_tableNúmero de hilos utilizados para compilar el índice columnstore de una sola tabla. Valores válidos: de 1 a 128.8

Cómo se implementa el ordenamiento

Ordenamiento al crear un nuevo índice columnstore

El proceso de ordenamiento replica el algoritmo de ordenamiento DDL (Data Definition Language) de los índices secundarios. Se admiten los modos de un solo hilo y de varios hilos:

  • Un solo hilo: ordenamiento por mezcla bidireccional estándar.

  • Varios hilos: ordenamiento por mezcla externo de k vías con árbol perdedor (loser tree) y ordenamiento por muestreo opcional.

El proceso se ejecuta en cuatro pasadas:

  1. Recorra los datos en el orden de la clave primaria, escriba las filas completas en los archivos de datos y agregue las columnas de la clave de ordenamiento al búfer de ordenamiento. Cada hilo escribe en su propio archivo de datos.

  2. Cuando el búfer de ordenamiento se llena, ordene su contenido según la combinación de la clave de ordenamiento y vacíelo en los archivos de mezcla.

  3. Ordene por mezcla los archivos de mezcla en pares y escriba el resultado ordenado en archivos temporales. Después, reemplace los archivos de mezcla con los archivos temporales.

  4. Repita la pasada 3 hasta que todos los archivos de mezcla estén ordenados. Luego, lea cada registro de los archivos de mezcla, recupere la fila completa de los archivos de datos mediante el desplazamiento y añádala al índice columnstore.

Ordenamiento incremental

El ordenamiento incremental es progresivo. Mejora el orden de los bloques de datos con el tiempo, pero no garantiza un orden total. El proceso es el siguiente:

  1. Agrupe todos los bloques de datos en pares y seleccione los grupos con mayor superposición en sus rangos de marcas de tiempo.

  2. Ordene por mezcla cada par para generar dos nuevos bloques de datos ordenados.

  3. Repita el proceso hasta que todos los bloques de datos estén ordenados.

El ordenamiento incremental mantiene el orden únicamente con base en la primera columna de la clave de ordenamiento.

Referencia de rendimiento

Tiempo de compilación frente a tiempo de consulta (TPC-H de 100 GB, tabla lineitem, 16 hilos)

El ordenamiento incrementa el tiempo de compilación, pero reduce significativamente el tiempo de consulta.

Conjunto de datos

Tiempo de compilación

Tiempo de consulta (TPC-H Q12)

Desordenado

6 minutos

7.47 s

Ordenado

35 minutos

1.25 s

Condiciones de la prueba: caché LRU = 10 GB, memoria del ejecutor = 10 GB. Consulta TPC-H Q12:

SELECT
    l_shipmode,
    SUM(CASE
        WHEN o_orderpriority = '1-URGENT' OR o_orderpriority = '2-HIGH'
        THEN 1
        ELSE 0
        END) AS high_line_count,
    SUM(CASE
        WHEN o_orderpriority <> '1-URGENT' AND o_orderpriority <> '2-HIGH'
        THEN 1
        ELSE 0
        END) AS low_line_count
    FROM
        orders,
        lineitem
    WHERE
        o_orderkey = l_orderkey
        AND l_shipmode in ('MAIL', 'SHIP')
        AND l_commitdate < l_receiptdate
        AND l_shipdate < l_commitdate
        AND l_receiptdate >= date '1994-01-01'
        AND l_receiptdate < date '1994-01-01' + interval '1' year
    GROUP BY
        l_shipmode
    ORDER BY
        l_shipmode;

Claves de ordenamiento combinadas con particionamiento (TPC-H de 1 TB, 32 núcleos, 256 GB de memoria)

A continuación se comparan los resultados de los índices columnstore desordenados con los índices columnstore que incluyen particiones y claves de ordenamiento. Definiciones de tablas utilizadas:

CREATE TABLE region ( r_regionkey  BIGINT NOT NULL,
                      r_name       CHAR(25) NOT NULL,
                      r_comment    VARCHAR(152)) COMMENT 'COLUMNAR=1';

CREATE TABLE nation ( n_nationkey  BIGINT NOT NULL,
                      n_name       CHAR(25) NOT NULL,
                      n_regionkey  BIGINT NOT NULL,
                      n_comment    VARCHAR(152)) COMMENT 'COLUMNAR=1';

CREATE TABLE part ( p_partkey     BIGINT NOT NULL,
                    p_name        VARCHAR(55) NOT NULL,
                    p_mfgr        CHAR(25) NOT NULL,
                    p_brand       CHAR(10) NOT NULL,
                    p_type        VARCHAR(25) NOT NULL,
                    p_size        BIGINT NOT NULL,
                    p_container   CHAR(10) NOT NULL,
                    p_retailprice DECIMAL(15,2) NOT NULL,
                    p_comment     VARCHAR(23) NOT NULL) COMMENT 'COLUMNAR=1';

CREATE TABLE supplier ( s_suppkey     BIGINT NOT NULL,
                        s_name        CHAR(25) NOT NULL,
                        s_address     VARCHAR(40) NOT NULL,
                        s_nationkey   BIGINT NOT NULL,
                        s_phone       CHAR(15) NOT NULL,
                        s_acctbal     DECIMAL(15,2) NOT NULL,
                        s_comment     VARCHAR(101) NOT NULL) COMMENT 'COLUMNAR=1';

CREATE TABLE partsupp ( ps_partkey     BIGINT NOT NULL,
                        ps_suppkey     BIGINT NOT NULL,
                        ps_availqty    BIGINT NOT NULL,
                        ps_supplycost  DECIMAL(15,2)  NOT NULL,
                        ps_comment     VARCHAR(199) NOT NULL) COMMENT 'COLUMNAR=1';

CREATE TABLE customer ( c_custkey     BIGINT NOT NULL,
                        c_name        VARCHAR(25) NOT NULL,
                        c_address     VARCHAR(40) NOT NULL,
                        c_nationkey   BIGINT NOT NULL,
                        c_phone       CHAR(15) NOT NULL,
                        c_acctbal     DECIMAL(15,2)   NOT NULL,
                        c_mktsegment  CHAR(10) NOT NULL,
                        c_comment     VARCHAR(117) NOT NULL) COMMENT 'COLUMNAR=1';

CREATE TABLE orders ( o_orderkey       BIGINT NOT NULL,
                      o_custkey        BIGINT NOT NULL,
                      o_orderstatus    CHAR(1) NOT NULL,
                      o_totalprice     DECIMAL(15,2) NOT NULL,
                      o_orderdate      DATE NOT NULL,
                      o_orderpriority  CHAR(15) NOT NULL,
                      o_clerk          CHAR(15) NOT NULL,
                      o_shippriority   BIGINT NOT NULL,
                      o_comment        VARCHAR(79) NOT NULL) COMMENT 'COLUMNAR=1'
                      PARTITION BY RANGE (year(`o_orderdate`))
                      (PARTITION p0 VALUES LESS THAN (1992) ENGINE = InnoDB,
                       PARTITION p1 VALUES LESS THAN (1993) ENGINE = InnoDB,
                       PARTITION p2 VALUES LESS THAN (1994) ENGINE = InnoDB,
                       PARTITION p3 VALUES LESS THAN (1995) ENGINE = InnoDB,
                       PARTITION p4 VALUES LESS THAN (1996) ENGINE = InnoDB,
                       PARTITION p5 VALUES LESS THAN (1997) ENGINE = InnoDB,
                       PARTITION p6 VALUES LESS THAN (1998) ENGINE = InnoDB,
                       PARTITION p7 VALUES LESS THAN (1999) ENGINE = InnoDB);

CREATE TABLE lineitem ( l_orderkey       BIGINT NOT NULL,
                        l_partkey        BIGINT NOT NULL,
                        l_suppkey        BIGINT NOT NULL,
                        l_linenumber     BIGINT NOT NULL,
                        l_quantity       DECIMAL(15,2) NOT NULL,
                        l_extendedprice  DECIMAL(15,2) NOT NULL,
                        l_discount       DECIMAL(15,2) NOT NULL,
                        l_tax            DECIMAL(15,2) NOT NULL,
                        l_returnflag     CHAR(1) NOT NULL,
                        l_linestatus     CHAR(1) NOT NULL,
                        l_shipdate       DATE NOT NULL,
                        l_commitdate     DATE NOT NULL,
                        l_receiptdate    DATE NOT NULL,
                        l_shipinstruct   CHAR(25) NOT NULL,
                        l_shipmode       CHAR(10) NOT NULL,
                        l_comment        VARCHAR(44) NOT NULL) COMMENT 'COLUMNAR=1'
                        PARTITION BY RANGE (year(`l_shipdate`))
                        (PARTITION p0 VALUES LESS THAN (1992) ENGINE = InnoDB,
                         PARTITION p1 VALUES LESS THAN (1993) ENGINE = InnoDB,
                         PARTITION p2 VALUES LESS THAN (1994) ENGINE = InnoDB,
                         PARTITION p3 VALUES LESS THAN (1995) ENGINE = InnoDB,
                         PARTITION p4 VALUES LESS THAN (1996) ENGINE = InnoDB,
                         PARTITION p5 VALUES LESS THAN (1997) ENGINE = InnoDB,
                         PARTITION p6 VALUES LESS THAN (1998) ENGINE = InnoDB,
                         PARTITION p7 VALUES LESS THAN (1999) ENGINE = InnoDB);

Después de importar los datos, aplique las claves de ordenamiento mediante la sintaxis ALTER TABLE anterior:

ALTER TABLE customer COMMENT='COLUMNAR=1 order_key=c_mktsegment';
ALTER TABLE nation COMMENT='COLUMNAR=1 order_key=n_name';
ALTER TABLE part COMMENT='COLUMNAR=1 order_key=p_brand,p_container,p_type';
ALTER TABLE region COMMENT='COLUMNAR=1 order_key=r_name';
ALTER TABLE orders COMMENT='COLUMNAR=1 order_key=o_orderkey,o_custkey,o_orderdate';
ALTER TABLE lineitem COMMENT='COLUMNAR=1 order_key=l_orderkey,l_linenumber,l_receiptdate,l_shipdate,l_partkey';

Resultados del tiempo de consulta (en segundos):

Consulta

Desordenado

Ordenado con particiones y claves de ordenamiento

Q3

71,951

36,566

Q4

46,679

32,015

Q6

34,652

4.4

Q7

74,749

34,166

Q12

86,742

28,586

Q14

50,248

12.56

Q15

79.22

21,113

Q20

51,746

10,178

Q21

216,942

148,459

Diferencias con el ordenamiento DDL de índices secundarios

El ordenamiento de índices columnstore difiere del ordenamiento DDL de índices secundarios en dos aspectos:

  • Flexibilidad de la clave de ordenamiento: el DDL de índices secundarios usa las columnas del índice como claves de ordenamiento. El ordenamiento de índices columnstore le permite especificar cualquier combinación de columnas como claves de ordenamiento, independientemente de la definición del índice.

  • Alcance de los datos: después de ordenar un índice columnstore, es necesario leer los datos completos de la fila. El DDL de índices secundarios solo almacena la porción correspondiente al índice (por ejemplo, únicamente el prefijo de una columna VARCHAR).

Pasos siguientes