Todos los productos
Search
Centro de documentos

Hologres:Acelerar la ejecución de SQL con fixed plans

Última actualización: Sep 05, 2026

Un fixed plan es una función de optimización del motor de ejecución exclusiva de Hologres. Este tema describe los requisitos previos y la configuración de parámetros necesarios para que una sentencia SQL sea apta para un fixed plan.

Contexto

Un fixed plan es un método de optimización del motor de ejecución exclusivo de Hologres. La ejecución tradicional de SQL involucra varios componentes, como el optimizador, el coordinador, el motor de consultas y el motor de almacenamiento. Por el contrario, un fixed plan utiliza una ruta directa que omite el optimizador, el coordinador y partes del motor de consultas para reducir la sobrecarga de procesamiento. El frontend fijo se conecta directamente al motor de consultas fijo, lo que mejora significativamente la eficiencia de ejecución de SQL. Esta optimización clave permite escrituras en tiempo real de alto throughput y consultas de alta concurrencia. Para obtener más información sobre los fixed plans, consulte product architecture.

En Hologres, los fixed plans se utilizan de forma predeterminada en los siguientes escenarios:

  • Escrituras en tiempo real en Hologres mediante Flink.

  • Escrituras en tiempo real en Hologres mediante Data Integration de DataWorks.

  • Escrituras en Hologres mediante Holo Client.

Para otros escenarios de escritura, puede configurar sus sentencias SQL para usar un fixed plan. Para obtener más información, consulte las siguientes secciones.

Nota

En estos escenarios, Hologres utiliza fixed plans de forma predeterminada para las sentencias SQL aptas. Sin embargo, no todas las sentencias SQL en estos escenarios son aptas.

Parámetros GUC relacionados

  • Lista de parámetros GUC

    Los siguientes parámetros se utilizan para configurar Fixed Plan. El valor de cada parámetro puede ser on u off. Todos los parámetros están habilitados de forma predeterminada en Holo Client y surten efecto a nivel de sesión.

    Parámetro

    Descripción

    Predeterminado

    Historial de cambios

    hg_experimental_enable_fixed_dispatcher

    Controla si se habilita la función de fixed plan para la instancia.

    Admite fixed plans para operaciones INSERT, UPDATE, DELETE y PrefixScan de una sola fila.

    on

    N/A.

    hg_experimental_enable_fixed_dispatcher_for_multi_values

    Controla si se usa un fixed plan para operaciones INSERT de varias filas.

    Nota

    No se garantiza la atomicidad. En inserciones de varias filas, una operación exitosa significa que se insertaron todas las filas. Si ocurre un error, el sistema devuelve un solo mensaje que puede indicar una inserción parcial o un fallo completo. La aplicación cliente es responsable de reintentar cualquier fila con errores.

    on

    A partir de Hologres V1.3.35, este parámetro GUC permite que las operaciones INSERT, UPDATE y DELETE de varias filas utilicen fixed plans.

    hg_experimental_enable_fixed_dispatcher_autofill_series

    Admite fixed plans para escrituras en tablas que contienen columnas de tipo SERIAL. Se recomienda habilitar este parámetro a nivel de sesión.

    on

    El valor predeterminado cambió a on en Hologres V1.3.25.

    hg_experimental_enable_fixed_dispatcher_for_update

    Admite fixed plans para operaciones UPDATE. Se recomienda habilitar este parámetro a nivel de sesión.

    off

    A partir de Hologres V1.3.25, el parámetro hg_experimental_enable_fixed_dispatcher_for_update está obsoleto. Las sentencias UPDATE aptas utilizan un fixed plan de forma predeterminada. Sin embargo, para actualizar varias filas, debe configurar set hg_experimental_enable_fixed_dispatcher_for_multi_values = on.

    hg_experimental_enable_fixed_dispatcher_for_delete

    Admite fixed plans para operaciones DELETE. Se recomienda habilitar este parámetro a nivel de sesión.

    off

    A partir de Hologres V1.3.25, el parámetro hg_experimental_enable_fixed_dispatcher_for_delete está obsoleto. Las sentencias DELETE aptas utilizan un fixed plan de forma predeterminada. Sin embargo, para eliminar varias filas, debe configurar set hg_experimental_enable_fixed_dispatcher_for_multi_values = on.

    hg_experimental_enable_fixed_dispatcher_for_scan

    Admite fixed plans para consultas PrefixScan.

    Nota

    Una consulta PrefixScan es una consulta sobre una tabla con una clave primaria compuesta donde las condiciones de consulta solo especifican las columnas iniciales de la clave primaria. Actualmente no se admiten fixed plans para consultas PrefixScan en tablas orientadas a columnas.

    off

    Se recomienda Hologres V1.3.35 o posterior.

    hg_experimental_enable_bhclient_cache_on_session

    Controla el modo de caché. Hay dos modos disponibles.

    • on: Usa el modo cached on session.

    • off: Usa el modo cached on fe.

    Nota

    La siguiente lista compara los modos cached on session y cached on fe.

    • cached on session: Cada sesión tiene su propio escritor y lector. Este modo proporciona un mayor throughput por sesión, pero tiene un inicio más lento, ya que el escritor y el lector requieren inicialización antes de la primera operación en cada tabla.

    • cached on fe: Todas las sesiones en un nodo FE comparten escritores y lectores. Los escritores y lectores no se cierran cuando termina una sesión, lo que elimina el tiempo de inicio.

    off

    N/A.

    hg_experimental_disable_fixed_planner_conflict_pk_check

    Controla si la en la sintaxis INSERT INTO <table_name> VALUES (...) ON CONFLICT(<column>) puede ser una columna que no sea clave primaria.

    • false: No compatible.

    • true: Compatible.

      Nota

      Si este parámetro GUC se establece en true, puede especificar una columna que no sea clave primaria. Sin embargo, la sentencia INSERT ON CONFLICT todavía procesa los datos basándose en si la clave primaria está duplicada, como si se hubiera especificado ON CONFLICT(pk).

    false

    • En versiones de Hologres desde V1.3 hasta V2.1.28, la columna especificada en ON CONFLICT(<column>) debe ser una columna de clave primaria.

    • Este parámetro solo está disponible en Hologres V2.1.29 y versiones posteriores de V2.1.x. Controla si la columna en ON CONFLICT(<column>) puede ser una clave no primaria. Este parámetro se elimina en V3.0 y posteriores, y no se requiere configuración.

  • Uso de parámetros GUC

    • Comprobar la configuración de un parámetro GUC

      Use el comando SHOW para comprobar la configuración de un parámetro GUC.

      SHOW <GUC_name>;

      Ejemplo:

      -- Check whether the fixed plan feature is enabled at the instance level.
      SHOW hg_experimental_enable_fixed_dispatcher;
    • Establecer un parámetro GUC

      • Establecer un parámetro GUC a nivel de sesión

        Puede usar el comando SET para configurar un parámetro GUC a nivel de sesión. La configuración se aplica solo a la sesión actual y se descarta cuando esta se cierra. Se recomienda incluir este comando antes de su sentencia SQL.

        SET <GUC_name> = <values>;

        GUC_name especifica el nombre del parámetro GUC, y values especifica el valor del parámetro.

        Ejemplo:

        -- Enable fixed plan for multi-row INSERT ON CONFLICT statements.
        SET hg_experimental_enable_fixed_dispatcher_for_multi_values = on;
      • Establecer un parámetro GUC a nivel de base de datos

        Use el comando ALTER DATABASE ... SET ... para establecer un parámetro GUC a nivel de base de datos. La configuración surte efecto para toda la base de datos. Para aplicar el cambio a la sesión actual, debe reconectarse. Esta configuración no se aplica a nuevas bases de datos; debe configurarla manualmente para cada una.

        ALTER DATABASE <db_name> SET <GUC_name> = <values>;

        db_name especifica el nombre de la base de datos, GUC_name especifica el nombre del parámetro GUC, y values especifica el valor del parámetro.

        Ejemplo:

        -- Enable the fixed plan feature at the database level.
        ALTER DATABASE <db_name> SET hg_experimental_enable_fixed_dispatcher = on;

Requisitos de tipos de datos

  • Las columnas de una tabla no pueden ser de tipo MONEY o MONEY ARRAY.

  • Los siguientes tipos de datos son compatibles para columnas en operaciones DML (INSERT, UPDATE y DELETE) y SELECT. Para las sentencias SELECT, este requisito se aplica tanto a las columnas de destino como a las columnas en la cláusula WHERE.

    • BOOLEAN (alias: BOOL)

    • SMALLINT

    • INTEGER (alias: INT, INT4)

    • BIGINT (alias: INT8)

    • FLOAT (alias: FLOAT4)

    • DOUBLE PRECISION (alias: FLOAT8)

    • CHAR(n)

    • VARCHAR(n) (En Hologres V1.1.79 y posteriores, VARCHAR puede usar Fixed Plan).

    • BYTEA

    • JSON y JSONB

    • TEXT (alias: VARCHAR)

    • TIMESTAMP WITH TIME ZONE (alias: TIMESTAMPTZ)

    • DATE

    • TIMESTAMP

    • DECIMAL (alias: NUMERIC)

    • ROARINGBITMAP

    • TIME (compatible en Hologres V2.2 y posteriores)

    • TIMETZ (compatible en Hologres V2.2 y posteriores)

    • Tipos de matriz

      • boolean[]

      • smallint[]

      • int4[]

      • int8[]

      • float4[]

      • float8[]

      • char(n)[]

      • varchar(n)[]

      • text[]

Escenarios de inserción

A partir de Hologres V3.2, puede usar la cláusula RETURNING en una sentencia INSERT que utilice un Fixed Plan para escribir en una tabla con clave primaria.

  • Sentencia Insert

    Se puede usar un Fixed Plan con las siguientes sentencias INSERT.

    -- Write a single row.
    INSERT INTO TABLE(col1,col2,col3..) VALUES(?,?,?..) ON conflict xxx;
    -- Write multiple rows.
    INSERT INTO TABLE(col1,col2,col3..) VALUES(?,?,?..),(?,?,?..) ON conflict xxx;
    Nota
    • Puede usar la sentencia INSERT para escribir datos en tablas internas, pero no en tablas externas.

    • Puede usar la sentencia INSERT para escribir datos en una tabla particionada. Hologres V1.3 y posteriores también admiten la escritura en una tabla particionada padre.

    • La palabra clave RETURNING no es compatible con sentencias INSERT en versiones de Hologres anteriores a V3.2. Es compatible en Hologres V3.2 y posteriores.

  • INSERT ON CONFLICT de una sola fila

    • Se admiten los siguientes escenarios:

      • Una sentencia INSERT sin una cláusula ON CONFLICT.

      • Una sentencia INSERT con una cláusula ON CONFLICT DO NOTHING.

      • Una sentencia INSERT con una cláusula ON CONFLICT DO UPDATE. Para usar un Fixed Plan, debe actualizar todas las columnas que no sean clave primaria (no PK) especificadas en la sentencia INSERT. Opcionalmente, puede actualizar las columnas de clave primaria (PK). La actualización debe usar el formato col = excluded.col. En Hologres V1.3 y posteriores, puede actualizar un subconjunto de columnas no PK, pero aún se requiere el formato col = excluded.col.

    • Ejemplo:

      BEGIN;
      CREATE TABLE test_insert_oneline (
          pk1 INT,
          pk2 INT,
          col1 INT,
          col2 INT,
          PRIMARY KEY (pk1, pk2)
      );
      COMMIT;
      
      -- Update all non-PK columns. A Fixed Plan can be used.
      INSERT INTO test_insert_oneline
          VALUES (1, 2, 3, 4)
      ON CONFLICT (pk1, pk2)
          DO UPDATE SET
              col1 = excluded.col1, col2 = excluded.col2;
      
      -- Update all columns, including PK and non-PK columns. A Fixed Plan can be used.
      INSERT INTO test_insert_oneline
          VALUES (1, 2, 3, 4)
      ON CONFLICT (pk1, pk2)
          DO UPDATE SET
              col1 = excluded.col1, col2 = excluded.col2, pk1 = excluded.pk1, pk2 = excluded.pk2;
      
      -- A Fixed Plan requires updating all non-PK columns specified in the INSERT statement. Because col2 is omitted, this statement is supported only in Hologres V1.3 and later.
      INSERT INTO test_insert_oneline
          VALUES (1, 2, 3, 4)
      ON CONFLICT (pk1, pk2)
          DO UPDATE SET
              col1 = excluded.col1;
      
      -- A Fixed Plan is not supported because the update uses a literal value instead of the required 'col = excluded.col' format.
      INSERT INTO test_insert_oneline
          VALUES (1, 2, 3, 4)
      ON CONFLICT (pk1, pk2)
          DO UPDATE SET
              col1 = excluded.col1, col2 = 5;
  • INSERT ON CONFLICT de varias filas

    • Para operaciones INSERT ON CONFLICT de varias filas, use la siguiente sintaxis:

      SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON;
      
      INSERT INTO TABLE (col1, col2, col3..)
          VALUES (?, ?, ?..), (?, ?, ?..)
      ON CONFLICT xxx;
      • Debe establecer el parámetro GUC hg_experimental_enable_fixed_dispatcher_for_multi_values = on;. En Hologres V1.3.35 y posteriores, este parámetro se establece en on de forma predeterminada.

      • Estas operaciones no garantizan atomicidad. Una operación exitosa escribe todas las filas. Si ocurre un error, es posible que se hayan escrito algunas filas o ninguna.

    • Alternativamente, puede usar la siguiente sintaxis para escribir varias filas:

      SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON;
      
      INSERT INTO TABLE SELECT
          unnest(ARRAY[TRUE, FALSE, TRUE]::bool[]),
          unnest(ARRAY[1, 2, 3]::int4[]),
          unnest(ARRAY[1.11, 2.222, 3]::float4[])
      ON CONFLICT xxx;
      • Debe establecer el parámetro GUC hg_experimental_enable_fixed_dispatcher_for_multi_values=on;.

      • No puede escribir datos en columnas de tipo matriz.

      • Las matrices en la función unnest deben convertirse explícitamente a los tipos de matriz de las columnas correspondientes.

      Ejemplo:

      BEGIN;
      CREATE TABLE test_insert_multiline (
          pk1 int8,
          col1 float4,
          PRIMARY KEY (pk1)
      );
      COMMIT;
      
      -- A Fixed Plan is supported.
      SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON;
      
      INSERT INTO test_insert_multiline
      SELECT
          unnest(ARRAY[1, 2, 3]::int8[]),
          unnest(ARRAY[1.11, 2.222, 3]::float4[])
      ON CONFLICT
          DO NOTHING;
      
      -- The ARRAY in the unnest function is not explicitly cast. A Fixed Plan is not supported.
      INSERT INTO test_insert_multiline
      SELECT
          unnest(ARRAY[1, 2, 3]),
          unnest(ARRAY[1.11, 2.222, 3])
      ON CONFLICT
          DO NOTHING;
      
      -- The first column is of the int8 type, so the array should be cast to int8[].
      -- In this example, it is cast to int4[], so a Fixed Plan is not supported.
      INSERT INTO test_insert_multiline
      SELECT
          unnest(ARRAY[1, 2, 3]::int4[]),
          unnest(ARRAY[1.11, 2.222, 3]::float4[])
      ON CONFLICT
          DO NOTHING;
  • Escenarios de actualización parcial

    Hologres admite la actualización de columnas específicas de una tabla mediante la clave primaria. También se puede usar un Fixed Plan para actualizaciones parciales si se cumplen las siguientes condiciones:

    • El número y orden de las columnas en la lista INSERT deben coincidir con los de la lista UPDATE.

    • La actualización debe usar el formato col = excluded.col.

  • UPSERT condicional

    Para manejar datos desordenados provenientes de fuentes superiores para filas con la misma clave primaria, Hologres proporciona una función similar a la operación CheckAndPut de HBase. Puede usar un Fixed Plan para sentencias INSERT o UPDATE con una cláusula condicional si se cumplen las siguientes condiciones:

    • Esta función es compatible con inserciones de una sola fila. Para inserciones de varias filas, debe establecer el parámetro GUC set hg_experimental_enable_fixed_dispatcher_for_multi_values=on;.

    • La cláusula WHERE debe contener solo una única columna no PK, y el operador de comparación debe ser uno de los siguientes: =, <>, >, >=, <, <=, IS NULL, o IS NOT NULL. Puede usar la función coalesce en esta columna no PK.

    Ejemplo:

    BEGIN;
    CREATE TABLE test_check_and_insert (
        pk INT,
        col INT,
        scn INT,
        PRIMARY KEY (pk)
    );
    COMMIT;
    
    -- A Fixed Plan is supported.
    -- Compare the existing column value with a constant.
    INSERT INTO test_check_and_insert AS old
        VALUES (1, 1, 1)
    ON CONFLICT (pk)
        DO UPDATE SET
            col = excluded.col, scn = excluded.scn
        WHERE
            old.scn > 0;
    
    -- Compare the existing column value with the new value being inserted.
    INSERT INTO test_check_and_insert AS old
        VALUES (1, 1, 1)
    ON CONFLICT (pk)
        DO UPDATE SET
            col = excluded.col, scn = excluded.scn
        WHERE
            old.scn > excluded.scn;
    
    -- If the existing value might be NULL, use coalesce.
    INSERT INTO test_check_and_insert AS old
        VALUES (1, 1, 1)
    ON CONFLICT (pk)
        DO UPDATE SET
            col = excluded.col, scn = excluded.scn
        WHERE
            coalesce(old.scn, 3) > 2;
    
    INSERT INTO test_check_and_insert AS old
        VALUES (1, 1, 1)
    ON CONFLICT (pk)
        DO UPDATE SET
            col = excluded.col, scn = excluded.scn
        WHERE
            coalesce(old.scn, 3) > excluded.scn;
    
    -- A Fixed Plan is supported.
    SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON;
    
    -- Compare the existing column value with a constant.
    INSERT INTO test_check_and_insert AS old
        VALUES (1, 1, 1), (2, 3, 4)
    ON CONFLICT (pk)
        DO UPDATE SET
            col = excluded.col, scn = excluded.scn
        WHERE
            old.scn > 3;
    
    -- The unnest syntax is also supported.
    INSERT INTO test_check_and_insert AS old
    SELECT
        unnest(ARRAY[5, 6, 7]::int[]),
        unnest(ARRAY[1, 1, 1]::int[]),
        unnest(ARRAY[1, 1, 1]::int[])
    ON CONFLICT (pk)
        DO UPDATE SET
            col = excluded.col,
            scn = excluded.scn
        WHERE
            old.scn > 3;
  • Columnas predeterminadas

    Puede usar un Fixed Plan para escribir en una tabla que contiene una columna con un valor DEFAULT si se cumplen las siguientes condiciones:

    • Esta función es compatible con inserciones de una sola fila. Para inserciones de varias filas, su instancia de Hologres debe ser V1.1.36 o posterior. Si su instancia es una versión anterior, actualícela. También debe establecer el parámetro GUC set hg_experimental_enable_fixed_dispatcher_for_multi_values=on; .

    • Hologres V1.3 y versiones posteriores admiten Fixed Plan para la cláusula Insert on conflict en tablas que tienen una columna Default. En instancias de versiones anteriores, Fixed Plan no es compatible con la cláusula Insert on conflict en tablas que tienen una columna Default.

    Ejemplo:

    BEGIN;
    CREATE TABLE test_insert_default (
        pk1 INT,
        col1 INT DEFAULT 99,
        PRIMARY KEY (pk1)
    );
    COMMIT;
    
    -- A Fixed Plan is supported.
    INSERT INTO test_insert_default (pk1)
        VALUES (1);
    
    -- This requires Hologres V1.1.36 or later.
    SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON;
    
    INSERT INTO test_insert_default (pk1)
        VALUES (1), (2), (3);
  • Columnas Serial

    Puede usar un Fixed Plan para escrituras de una o varias filas en una tabla con una columna SERIAL de incremento automático si se cumplen las siguientes condiciones:

    • Debe establecer el parámetro GUC set hg_experimental_enable_fixed_dispatcher_autofill_series=on;. En Hologres V1.3.25 y posteriores, el valor predeterminado de este parámetro es on.

    • Para inserciones de varias filas, también debe establecer el parámetro GUC set hg_experimental_enable_fixed_dispatcher_for_multi_values=on;.

    Ejemplo:

    BEGIN;
    CREATE TABLE test_insert_serial (
        pk1 INT,
        col1 SERIAL,
        PRIMARY KEY (pk1)
    );
    COMMIT;
    
    -- A Fixed Plan is supported.
    SET hg_experimental_enable_fixed_dispatcher_autofill_series = ON;
    
    INSERT INTO test_insert_serial (pk1)
        VALUES (1);
    
    -- A Fixed Plan is supported.
    SET hg_experimental_enable_fixed_dispatcher_autofill_series = ON;
    
    SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON;
    
    INSERT INTO test_insert_serial (pk1)
        VALUES (1), (2), (3);

Escenarios de actualización

  • Sentencia UPDATE

    Una sentencia UPDATE con las siguientes cláusulas puede usar un fixed plan.

    SET hg_experimental_enable_fixed_dispatcher_for_update = ON;
    
    UPDATE TABLE SET col1 = ?,col2 = ? WHERE pk1 = ? AND pk2 = ?;
  • Notas de uso

    Una sentencia UPDATE puede usar un fixed plan si se cumplen las siguientes condiciones:

    • Puede actualizar tablas internas y tablas particionadas hijas, pero no tablas externas ni tablas particionadas padre. La tabla debe tener una clave primaria (PK).

    • Debe ejecutar el comando SET hg_experimental_enable_fixed_dispatcher_for_update = ON;. A partir de Hologres V1.3.25, este parámetro está obsoleto. Las sentencias UPDATE aptas usan automáticamente un fixed plan. Sin embargo, para actualizar varias filas a la vez, debe ejecutar el comando SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON;.

    • Las columnas especificadas en la cláusula SET no pueden ser columnas de clave primaria.

    • La cláusula WHERE debe especificar todas las columnas de clave primaria. En Hologres V1.3 y posteriores, la última condición en la cláusula WHERE puede ser sobre una columna que no sea clave primaria y puede usar los operadores de comparación =, <>, >, >=, <, <=, IS NULL, y IS NOT NULL o la función coalesce.

    • Puede usar pk in (?,?,?) or pk = ANY(...) para actualizar varias filas en una sola sentencia. Por ejemplo, pk1 in (1,2) and pk2 = any('{3,4}') and pk3 = 5 actualiza las cuatro filas: (1,3,5), (1,4,5), (2,3,5), y (2,4,5).

    • Cada columna en la cláusula WHERE puede tener solo una condición. Las condiciones idénticas se tratan como una sola condición.

    Ejemplos:

    BEGIN;
    CREATE TABLE test_update (
        pk1 INT,
        pk2 INT,
        col1 INT,
        col2 INT,
        PRIMARY KEY (pk1, pk2)
    );
    COMMIT;
    
    -- Fixed plan supported.
    SET hg_experimental_enable_fixed_dispatcher_for_update = ON;
    
    UPDATE
        test_update
    SET
        col1 = 1,
        col2 = 2
    WHERE
        pk1 = 3
        AND pk2 = 4;
    
    -- Fixed plan supported.
    SET hg_experimental_enable_fixed_dispatcher_for_update = ON;
    
    UPDATE
        test_update
    SET
        col1 = 1
    WHERE
        pk1 = 3
        AND pk2 = 4;
    
    -- Fixed plan supported (Hologres V1.3+, WHERE clause with a non-primary key column).
    SET hg_experimental_enable_fixed_dispatcher_for_update = ON;
    UPDATE test_update SET col1 = 1 WHERE pk1 = 3 AND pk2 = 4 AND col1 > 3;
    
    -- Fixed plan supported (Hologres V1.3+, WHERE clause with a non-primary key column and coalesce).
    SET hg_experimental_enable_fixed_dispatcher_for_update = ON;
    UPDATE test_update SET col1 = 1 WHERE pk1 = 3 AND pk2 = 4 AND coalesce(col1, 4) <> 1;
    
    -- Fixed plan supported.
    SET hg_experimental_enable_fixed_dispatcher_for_update = ON;
    
    UPDATE
        test_update
    SET
        col1 = 1,
        col2 = 2
    WHERE
        pk1 IN (1, 2)
        AND pk2 = ANY ('{3,4}');
    
    -- Fixed plan supported (Hologres V1.3+, WHERE clause with a non-primary key column).
    SET hg_experimental_enable_fixed_dispatcher_for_update = ON;
    UPDATE test_update SET col1 = 1 WHERE pk1 IN (1, 2) AND pk2 = ANY('{3,4}') AND col1 > 3;
    
    -- Fixed plan not supported (multiple conditions on pk1).
    UPDATE
        test_update
    SET
        col1 = 1,
        col2 = 2
    WHERE
        pk1 = 3
        AND pk1 = 4;
    
    -- Fixed plan not supported (multiple conditions on pk1).
    UPDATE
        test_update
    SET
        col1 = 1,
        col2 = 2
    WHERE
        pk1 IN (1, 2)
        AND pk1 = 1;
    
    -- Fixed plan supported (multiple identical conditions on pk1).
    SET hg_experimental_enable_fixed_dispatcher_for_update = ON;
    
    UPDATE
        test_update
    SET
        col1 = 1,
        col2 = 2
    WHERE
        pk1 IN (1, 2)
        AND pk1 IN (1, 2)
        AND pk2 = 4;

Escenarios de eliminación

  • Sentencia DELETE

    La siguiente sentencia muestra cómo usar un fixed plan para una operación DELETE:

    SET hg_experimental_enable_fixed_dispatcher_for_delete = ON;
    
    DELETE FROM TABLE
    WHERE pk1 = ?
        AND pk2 = ?
        AND pk3 = ?;
  • Notas de uso

    Una operación DELETE puede usar un fixed plan si cumple las siguientes condiciones:

    • La operación debe dirigirse a una tabla interna o a una tabla hija, no a una tabla externa ni a una tabla particionada padre. La tabla también debe tener una clave primaria (PK).

    • Debe establecer el parámetro GUC hg_experimental_enable_fixed_dispatcher_for_delete=on;. En Hologres V1.3.25 y posteriores, este parámetro está obsoleto. Las sentencias DELETE aptas usan un fixed plan de forma predeterminada. Sin embargo, para eliminar varias filas, debe ejecutar el comando set hg_experimental_enable_fixed_dispatcher_for_multi_values =on.

    • La cláusula WHERE debe especificar condiciones para todas las columnas de clave primaria. A partir de Hologres V1.3, la última condición en la cláusula WHERE puede aplicarse a un campo que no sea clave primaria, lo cual admite los operadores de comparación =, <>, >, >=, <, <=, IS NULL, y IS NOT NULL, así como la función coalesce.

    • Puede usar pk in (?,?,?) or pk = ANY() para eliminar varias filas en una sola operación. Por ejemplo, pk1 in (1,2) and pk2 = any('{3,4}') and pk3 = 5 elimina las cuatro filas: (1,3,5), (1,4,5), (2,3,5), y (2,4,5).

    • Cada columna puede tener solo una condición en la cláusula WHERE. Las condiciones duplicadas se tratan como una sola condición.

    Ejemplo:

    BEGIN;
    CREATE TABLE test_delete (
        pk1 INT,
        pk2 INT,
        col1 INT,
        col2 INT,
        PRIMARY KEY (pk1, pk2)
    );
    COMMIT;
    
    -- This DELETE statement uses a fixed plan. For more scenarios, see the examples for the UPDATE statement.
    SET hg_experimental_enable_fixed_dispatcher_for_delete = ON;
    
    DELETE FROM test_delete
    WHERE pk1 = 1
        AND pk2 = 2;
    

Escenarios SELECT

  • Sentencias SELECT

    Se admite un fixed plan para sentencias SELECT que contienen cláusulas específicas.

    SELECT
        col1,
        col2,
        col3,
    ...
    FROM
        TABLE
    WHERE
        pk1 = ?
        AND pk2 = ?
        AND pk3 = ?;
    
    • La consulta debe dirigirse a una tabla interna, no a una tabla externa.

    • La consulta debe dirigirse a una tabla particionada hija, no a una tabla particionada padre.

    • La tabla debe tener una clave primaria (PK).

  • Escenarios de consulta puntual (clave/valor)

    Las siguientes condiciones se aplican a las consultas puntuales que usan un fixed plan.

    • La cláusula WHERE debe contener todas y únicamente las columnas de la clave primaria.

    • Puede usar pk in (?,?,?) or pk = ANY() para consultar varias filas a la vez. Por ejemplo, pk1 in (1,2) and pk2 = any('{3,4}') and pk3 = 5 consulta cuatro filas: (1,3,5),(1,4,5),(2,3,5),(2,4,5).

    • Cada columna puede tener solo una condición. Las condiciones duplicadas se tratan como una sola.

    • Si se incluye una cláusula LIMIT, su valor debe ser >0.

    Ejemplo:

    BEGIN;
    CREATE TABLE test_select (
        pk1 INT,
        pk2 INT,
        col1 INT,
        col2 INT,
        PRIMARY KEY (pk1, pk2)
    );
    CALL set_table_property ('test_select', 'orientation', 'row');
    COMMIT;
    
    --A fixed plan is supported for this query.
    SELECT * FROM test_select WHERE pk1 = 1 AND pk2 = 2;
  • Escenarios PrefixScan

    • Cláusulas PrefixScan

      Un PrefixScan se aplica a consultas en tablas con una clave primaria compuesta. Estas consultas utilizan el principio de coincidencia de prefijo más a la izquierda para filtrar según un prefijo de las columnas de clave primaria. El siguiente código muestra ejemplos de dichas cláusulas:

      SET hg_experimental_enable_fixed_dispatcher_for_scan = on;
      SELECT col1,col2,col3,... FROM TABLE WHERE pk1 = ? AND pk2 = ?;
      SELECT col1,col2,col3,... FROM TABLE WHERE pk1 = ? AND pk2 < ?;--From Hologres V1.1.48, the last column of the PK prefix can be a range condition.
      SELECT col1,col2,col3,... FROM TABLE WHERE pk1 = ? AND pk2 BETWEEN ? AND ?;--From Hologres V1.1.48, the last column of the PK prefix can be a range condition.                                
    • Uso de PrefixScan

      Las siguientes condiciones deben cumplirse para usar PrefixScan:

      • El parámetro GUC hg_experimental_enable_fixed_dispatcher_for_scan=on; debe estar establecido, y la instancia de Hologres debe ser V1.3.35 o posterior.

      • La tabla debe tener una clave de distribución, y la cláusula WHERE debe incluir todas las columnas de la clave de distribución.

      • La cláusula WHERE solo puede contener un prefijo de la clave primaria. En Hologres V1.1.48 y posteriores, también se puede especificar una condición de rango (con límite superior e inferior) para la última columna del prefijo de la clave primaria.

        Nota

        Definición de prefijo: si una clave primaria es (pk1,pk2,pk3), entonces (pk1) y (pk1,pk2) son sus prefijos.

      • Solo las tablas orientadas a filas y las tablas híbridas de fila-columna admiten PrefixScan.

      • Cada columna puede tener solo una condición. Las condiciones duplicadas se tratan como una sola.

      • Si se incluye una cláusula LIMIT, su valor debe ser > 0.

      Nota

      Un PrefixScan devuelve todas las filas de resultados a la vez. Si el tamaño total en bytes de los resultados supera el valor de hg_experimental_fixed_scan_bytesize_limit, se devuelve un error: scan result size larger than fixed scan size limit. Puede configurar el parámetro hg_experimental_fixed_scan_bytesize_limit con un valor adecuado para su escenario. El valor predeterminado es 1,048,576 (1 MB).

      Por ejemplo, suponga que la clave primaria de una tabla es (pk1,pk2,pk3,pk4) y su clave de distribución es pk1,pk3.

      BEGIN;
      CREATE TABLE test_select_prefix (
          pk1 INT,
          pk2 INT,
          pk3 INT,
          pk4 INT,
          PRIMARY KEY (pk1, pk2, pk3, pk4)
      );
      CALL set_table_property ('test_select_prefix', 'orientation', 'row');
      CALL set_table_property ('test_select_prefix', 'distribution_key', 'pk1,pk3');
      COMMIT;
      
      --Does not include all distribution key columns. A fixed plan cannot be used.
      SELECT * FROM test_select_prefix WHERE pk1 = ? AND pk2 = ?;
      --Not a prefix of the primary key. A fixed plan cannot be used.
      SELECT * FROM test_select_prefix WHERE pk1 = ? AND pk3 = ?;
      
      --A fixed plan can be used.
      SET hg_experimental_enable_fixed_dispatcher_for_scan = ON;
      
      SELECT * FROM test_select_prefix WHERE pk1 = ? AND pk2 = ? AND pk3 = ?;
      

      Puede usar pk in (?,?,?) o pk = ANY() para consultar varias filas a la vez, como se muestra en los siguientes ejemplos.

      pk1 IN (1,2) AND pk2 = 3 --Equivalent to scanning two key groups: (1,3) and (2,3).
      pk2 =any('{3,4}') AND pk1 IN (1,2) --Equivalent to scanning four key groups: (1,3), (1,4), (2,3), and (2,4).
    • Ejemplo de uso

      BEGIN;
      CREATE TABLE test_scan (
          pk1 INT,
          pk2 INT,
          pk3 INT,
          col1 INT,
          PRIMARY KEY (pk1, pk2, pk3)
      );
      CALL set_table_property ('test_scan', 'orientation', 'row');
      CALL set_table_property ('test_scan', 'distribution_key', 'pk1,pk2');
      COMMIT;
      
      INSERT INTO test_scan
          VALUES (1, 2, 3, 4);
      
      --A fixed plan is supported.
      SET hg_experimental_enable_fixed_dispatcher_for_scan = ON;
      
      SELECT * FROM test_scan WHERE pk1 = 1 AND pk2 = 2;
      
      --A fixed plan is supported.
      SET hg_experimental_enable_fixed_dispatcher_for_scan = ON;
      
      SELECT * FROM test_scan WHERE pk1 = 1 AND pk2 IN (2, 3);
      
      --A fixed plan is supported.
      SET hg_experimental_enable_fixed_dispatcher_for_scan = ON;
      
      SELECT * FROM test_scan WHERE pk1 = ANY ('{3,4}') AND pk2 IN (2, 3);
      
      --A fixed plan is supported. The last column of the PK is a range condition. Requires Hologres V1.1.48 or later.
      SET hg_experimental_enable_fixed_dispatcher_for_scan = ON;
      
      SELECT * FROM test_scan WHERE pk1 = 1 AND pk2 = 1 AND pk3 > 1 AND pk3 < 4;
      
      --A fixed plan is supported. The last column of the PK is a range condition. Requires Hologres V1.1.48 or later.
      SET hg_experimental_enable_fixed_dispatcher_for_scan = ON;
      
      SELECT * FROM test_scan WHERE pk1 = 1 AND pk2 = 1 AND pk3 BETWEEN 1 AND 4;
      
      --Does not include all distribution key columns. A fixed plan is not supported.
      SELECT * FROM test_scan WHERE pk1 = 1;
      
      --Does not match a primary key prefix. A fixed plan is not supported.
      SELECT * FROM test_scan WHERE pk2 = 2;
  • Escenarios de paginación

    En Hologres V3.2 y posteriores, el plan fijo admite consultas PrefixScan que utilizan paginación.

    Nota
    • De forma predeterminada, los resultados de un PrefixScan se ordenan en orden ascendente de la clave primaria. En el siguiente ejemplo de SQL, un PrefixScan en pk1 y pk2 devuelve resultados ordenados en orden ascendente de pk3.

    • Para especificar el orden de clasificación, puede definir el orden de las columnas en la clustering key y establecer el parámetro GUC correspondiente en su consulta, lo que ordena los resultados según la clave de agrupamiento. Las columnas de la clave de agrupamiento deben ser idénticas a las columnas de la clave primaria. En el siguiente ejemplo de SQL, para ordenar los resultados en orden descendente, puede establecer la última columna de la clave de agrupamiento en pk3:desc.

    • Orden ascendente

      -- Create a table.
      CREATE TABLE test_scan(
        pk1 INT, 
        pk2 INT, 
        pk3 INT, 
        col1 INT, 
        PRIMARY KEY(pk1, pk2, pk3)
      ) WITH (
        orientation = 'row',
        distribution_key = 'pk1,pk2',
        clustering_key = 'pk1:asc,pk2:asc,pk3:asc'
      );
      
      -- Insert data.
      INSERT INTO test_scan VALUES (1,2,3,4),(1,2,5,6),(1,2,7,8);
      
      -- `offset + limit` is supported. Based on PrefixScan, this query returns a specified number of rows starting from a specified offset.
      SET hg_experimental_enable_fixed_dispatcher_for_scan = on;
      -- By default, the results are sorted in ascending order of pk3.
      SELECT * FROM test_scan WHERE pk1 = 1 AND pk2 = 2 OFFSET 1 limit 2;
    • Orden descendente

      -- Create a table.
      CREATE TABLE test_scan(
        pk1 INT, 
        pk2 INT, 
        pk3 INT, 
        col1 INT, 
        PRIMARY KEY(pk1, pk2, pk3)
      ) WITH (
        orientation = 'row',
        distribution_key = 'pk1,pk2',
        clustering_key = 'pk1:asc,pk2:asc,pk3:desc'
      );
      
      -- Insert data.
      INSERT INTO test_scan VALUES (1,2,3,4),(1,2,5,6),(1,2,7,8);
      
      -- Enable both of the following GUC parameters to sort the results in descending order of pk3.
      SET hg_experimental_enable_fixed_dispatcher_for_scan = on;
      SET hg_experimental_enable_fixed_dispatcher_for_clustering_key_scan = on;
      SELECT * FROM test_scan WHERE pk1 = 1 AND pk2 = 2 OFFSET 1 limit 2;

Escenarios de COPY

A partir de Hologres V1.3.17, la instrucción COPY puede utilizar un plan fijo, una función conocida como Fixed Copy. Para ver una comparación entre COPY y Fixed Copy, consulte Best practices for batch write.

Para obtener más información sobre los parámetros de Fixed Copy, consulte COPY. A continuación se muestra un ejemplo:

COPY table_name (column0, column1, column2)
FROM
    STDIN WITH (
        format BINARY,
        stream_mode TRUE,
        on_conflict UPDATE);

Cuando se omiten columnas en una instrucción COPY, el comportamiento es el siguiente:

  • Si la instrucción COPY especifica un subconjunto de las columnas de la tabla, realiza una actualización parcial. Por ejemplo:

    CREATE TABLE t0 (
        id INT NOT NULL,
        name TEXT,
        age INT,
        PRIMARY KEY (id)
    );
    
    COPY t0 (id,
        name)
    FROM
        STDIN WITH (stream_mode TRUE, on_conflict UPDATE);
    
    -- The COPY statement above is equivalent to the following INSERT INTO statement:
    INSERT INTO t0 (id, name)
        VALUES (?, ?)
    ON CONFLICT (id)
        DO UPDATE SET id = excluded.id, name = excluded.name;
  • Si las columnas omitidas tienen un valor predeterminado, la instrucción COPY se comporta de la siguiente manera:

    CREATE TABLE t0 (
        id INT NOT NULL,
        name TEXT,
        age INT DEFAULT 0,
        PRIMARY KEY (id)
    );
    
    COPY t0 (id,
        name)
    FROM
        STDIN WITH (stream_mode TRUE, on_conflict UPDATE);
    
    -- The COPY statement above is equivalent to the following INSERT INTO statement:
    -- If the ID does not exist, a new row is inserted, and the age column is set to its default value.
    -- If the ID already exists, the row is updated, and the age column remains unchanged.
    INSERT INTO t0 (id, name, age)
        VALUES (?, ?, DEFAULT)
    ON CONFLICT (id)
        DO UPDATE SET id = excluded.id, name = excluded.name;
    

Expresiones en el plan fijo

A partir de Hologres V3.2, la función de plan fijo admite expresiones en instrucciones SQL. Para obtener más información sobre las expresiones en PostgreSQL, consulte Expresiones. Los escenarios compatibles incluyen:

  • Instrucciones INSERT:

    • Cláusula VALUES

    • Cláusula INSERT ON CONFLICT DO UPDATE

    • Condición de filtro en la cláusula INSERT ON CONFLICT WHERE

    • Cláusula RETURNING

  • Instrucciones SELECT:

    La lista de SELECT

Limitaciones

  • Solo se admiten expresiones y funciones escalares. No se admiten funciones de agregación, funciones de ventana ni subconsultas.

  • Para las instrucciones INSERT, las expresiones y funciones utilizadas en cláusulas distintas a la cláusula VALUES deben ser compatibles con HQE.

  • Para las instrucciones SELECT, el plan fijo solo admite expresiones y funciones IMMUTABLE que aceptan un argumento constante.

  • Para utilizar esta función, debe habilitar el siguiente parámetro:

    -- Enable at the session level
    SET hg_experimental_enable_fixed_plan_expression = on;
    
    -- Enable at the database level
    ALTER DATABASE <db_name> SET hg_experimental_enable_fixed_plan_expression = on;

Ejemplos

  • Uso de expresiones en las cuatro cláusulas compatibles de una instrucción INSERT

    -- Create a table.
    CREATE TABLE test_t (
        id INT PRIMARY KEY,
        col INT,
        ts TIMESTAMP
    )
    WITH (
        orientation = 'row',
        distribution_key = 'id'
    );
    
    -- Enable the GUC parameter.
    SET hg_experimental_enable_fixed_plan_expression = ON;
    
    -- Use an expression in the VALUES clause.
    INSERT INTO test_t VALUES (1, 1, now());
    
    -- Use an expression in the ON CONFLICT DO UPDATE clause.
    INSERT INTO test_t AS old 
        VALUES (1, 1, now())
        ON CONFLICT (id) 
        DO UPDATE SET col = excluded.col + old.col, ts = excluded.ts;
    
    -- Use an expression in the ON CONFLICT WHERE clause.
    INSERT INTO test_t AS old
        VALUES (1, 1, now())
        ON CONFLICT (id)
        DO UPDATE SET col = excluded.col + old.col, ts = excluded.ts
        WHERE excluded.ts > old.ts;
    
    -- Use an expression in the RETURNING clause.
    INSERT INTO test_t AS old
        VALUES (1, 1, now())
        ON CONFLICT (id)
        DO UPDATE SET col = excluded.col + old.col, ts = excluded.ts
        WHERE excluded.ts > old.ts
        RETURNING 2 * col, ts;
  • Uso de expresiones en la lista SELECT de una instrucción SELECT

    • Consulta puntual mediante una clave principal completa: este ejemplo extrae el valor de una clave de una columna JSONB.

      -- Create a table.
      CREATE TABLE test_t (
          id int PRIMARY KEY,
          ts TIMESTAMP NOT NULL,
          col JSONB
      )
      WITH (
          orientation = 'row',
          distribution_key = 'id'
      );
      
      -- Use expressions in the SELECT list. JSONB operators are supported.
      SELECT
          (col ->> 'b')::int + (col ->> 'a')::int,
          date_trunc('day', ts)
      FROM
          test_t
      WHERE
          id = 1;
    • PrefixScan mediante un prefijo de clave principal.

      -- Create a table.
      CREATE TABLE test_t (
          id INT,
          ts TIMESTAMP NOT NULL,
          col JSONB,
          PRIMARY KEY (id, ts)
      )
      WITH (
          orientation = 'row',
          distribution_key = 'id'
      );
      
      -- Enable the GUC parameter.
      SET hg_experimental_enable_fixed_dispatcher_for_scan = TRUE;
      
      -- Use expressions in the SELECT list.
      SELECT
          (col ->> 'b')::int + (col ->> 'a')::int,
          date_trunc('day', ts)
      FROM
          test_t
      WHERE
          id = 1;
  • Una instrucción SELECT no puede ser optimizada por el plan fijo si contiene funciones no IMMUTABLE o funciones que no aceptan un argumento constante.

    -- Create a table.
    CREATE TABLE test_t (
        id INT PRIMARY KEY,
        ts TIMESTAMP NOT NULL,
        col JSONB
    )
    WITH (
        orientation = 'row',
        distribution_key = 'id'
    );
    
    -- The random() function is not immutable and is not supported by Fixed Plan.
    SELECT
        id + random()
    FROM
        test_t
    WHERE
        id = 1;
    
    -- The toString function does not accept a constant argument and is not supported by Fixed Plan.
    SELECT
        toString (id)
    FROM
        test_t
    WHERE
        id = 1;

Verificación de un plan fijo

  • En la consola, las instrucciones INSERT, UPDATE y DELETE ejecutadas mediante un plan fijo aparecen como tipo SDK en el panel Real-time Import (RPS). Se recomienda utilizar planes fijos para estas operaciones de escritura en tiempo real con el fin de mejorar la eficiencia de la actualización de datos.RPS

  • Para ver el plan de ejecución de SQL, ejecute una instrucción EXPLAIN. Si el plan de ejecución devuelto contiene FixedXXXNode, significa que se ha activado un plan fijo, como se muestra en la siguiente figura. Si el plan de ejecución no contiene FixedXXXNode, revise las condiciones de compatibilidad descritas en las secciones anteriores y compruebe que su instrucción cumple con los requisitos.验证fixedplan

Ajuste de rendimiento

Si aún necesita ajustar el rendimiento con un plan fijo habilitado, puede utilizar los siguientes métodos.

  • Analice el plan de ejecución para identificar cuellos de botella de rendimiento. Ejecute EXPLAIN en una instrucción SQL para ver el tiempo consumido en cada etapa y localizar los cuellos de botella.

  • Las versiones 1.1.49 y posteriores de Hologres están optimizadas para consultas puntuales que utilizan un plan fijo, lo que mejora el throughput en más de un 30% en escenarios a gran escala. Para aprovechar esta mejora, actualice su instancia a la versión V1.1.49 o posterior.

  • Utilice procesamiento por lotes en el cliente con un tamaño de lote de 512 o un múltiplo de 512. Holo Client gestiona el procesamiento por lotes automáticamente.

Preguntas frecuentes

  • Síntoma: al intentar conectarse a Hologres, se produce el siguiente error: role/database does not exist.

    • Causa: el usuario o la base de datos especificados no existen.

    • Solución: compruebe su información de conexión y asegúrese de que el nombre de usuario y el nombre de la base de datos sean correctos.

      Inicie sesión en la consola de Hologres. Busque la instancia objetivo y haga clic en Manage en la columna Actions. Haga clic en Database Management. Luego podrá verificar el nombre de usuario en la página Users y el nombre de la base de datos en la página Database Authorization.

  • Síntoma: durante una operación de escritura de datos, se produce el siguiente error: the requested table name: xxx (id: xx, version: xx) mismatches the version of the table (id: xx, version: xx) from server.

    • Causa: los metadatos de la tabla cambian durante la operación de escritura de datos (por ejemplo, se agrega una columna), lo que modifica la versión de la tabla.

    • Solución: restablezca la conexión. El plan fijo recuperará entonces los nuevos metadatos de la tabla para completar la operación de escritura.