Usar la ejecución paralela para la parte SELECT de una consulta INSERT INTO ... SELECT
puede mejorar el rendimiento de las consultas de AlloyDB para PostgreSQL, especialmente
en el caso de las tablas particionadas y las consultas complejas.
Al paralelizar el subplan SELECT, la base de datos usa varios procesos de trabajo para recuperar datos. A continuación, la base de datos inserta los datos obtenidos en la tabla de destino. Esta división del trabajo puede mejorar el rendimiento de la base de datos.
Cómo funcionan los planes de consulta paralelos en PostgreSQL
En PostgreSQL, el optimizador de consultas puede crear un plan paralelo para una consulta completa o para una parte de una consulta. Cuando se genera un plan paralelo, se añade un nodo Gather
o Gather Merge en la parte superior del plan.
Este nodo coordina varios procesos de trabajo paralelos. Cada trabajador ejecuta una parte de la tarea, por ejemplo, analizar una parte de una tabla. El nodo Gather recoge los resultados de todos los trabajadores y los envía a la siguiente fase de la consulta o de vuelta al cliente.
Por ejemplo, el siguiente plan de consulta muestra un nodo Gather que tiene previsto usar cinco procesos de trabajo para realizar un análisis secuencial paralelo en la tabla t1.
EXPLAIN SELECT * FROM t1;
QUERY PLAN
-------------------------------------------------------------
Gather (cost=0.00..143359.76 rows=9999878 width=60)
Workers Planned: 5
-> Parallel Seq Scan on t1 (cost=0.00..143359.76 rows=1999976 width=60)
(3 rows)
Ejecución en paralelo de instrucciones INSERT...SELECT
AlloyDB mejora el rendimiento de INSERT INTO ... SELECT mediante el uso de varios procesos de trabajo para paralelizar la instrucción SELECT.
Esta división del trabajo puede mejorar el rendimiento de la base de datos.
La consulta debe ser segura para el paralelismo y no debe haber ninguna condición que impida la paralelización.
Muchas operaciones de bases de datos usan declaraciones INSERT INTO ... SELECT para añadir filas a una tabla. A menudo, la parte SELECT de la instrucción es la que más recursos consume de la consulta.
La función se controla mediante los siguientes parámetros de configuración:
enable_parallel_select_for_insert_select: habilita o inhabilita la función . Este parámetro está activado de forma predeterminada en PostgreSQL 14 y versiones posteriores.enable_parallel_select_for_insert_select_into_part_table: habilita o inhabilita la función que te permite insertar datos en tablas particionadas. Este parámetro está desactivado de forma predeterminada en PostgreSQL 16 y versiones posteriores.
Para que el optimizador de consultas considere un plan paralelo, la INSERT SELECT
instrucción debe ser segura para el paralelismo. Esto significa que ninguna parte de la operación puede contener funciones o expresiones que no se puedan ejecutar de forma segura en paralelo. Si se determina que alguna parte de la consulta no es segura para el paralelismo, el optimizador vuelve a un plan no paralelo. Para obtener más información, consulta parallel-safety.
Condiciones que impiden la ejecución en paralelo
El optimizador de consultas no usa un plan paralelo si la instrucción INSERT SELECT
se considera no segura para el paralelismo. Las siguientes condiciones impiden la paralelización:
- La tabla de destino es una tabla externa.
- La consulta usa una expresión de tabla común (CTE) modificable que contiene una instrucción de modificación de datos, por ejemplo,
DELETE. - Un índice de la tabla de destino usa una expresión o función no segura en paralelo.
- Una columna de la tabla de destino tiene un valor predeterminado que usa una función paralela no segura.
- Un activador de la tabla de destino usa una expresión o una función no segura en paralelo.
- La tabla de destino tiene una columna DOMAIN con una restricción
CHECKque usa una función paralela no segura. - Una restricción
CHECKen la tabla de destino contiene una expresión o función paralela no segura. - La tabla de destino es una tabla con particiones y
enable_parallel_select_for_insert_select_into_part_tableestá inhabilitado.
Antes de empezar
En este documento se presupone que tienes una base de datos de AlloyDB. Para crear una base de datos, consulta Crear un clúster y su instancia principal y Crear y gestionar una base de datos.
Roles obligatorios
Para obtener los permisos que necesitas para cambiar las marcas de la base de datos a nivel de sesión, pide a tu administrador que te conceda el rol de gestión de identidades y accesos (IAM) de usuario de base de datos de AlloyDB (roles/alloydb.databaseUser) en tu proyecto. Para obtener más información sobre cómo conceder roles, consulta el artículo Gestionar acceso a proyectos, carpetas y organizaciones.
Habilitar parámetros de ejecución paralela
Para habilitar la ejecución en paralelo de tablas de destino particionadas, sigue estos pasos:
En la Google Cloud consola, ve a la página Clusters.
Selecciona un clúster de la lista.
En el menú de navegación, haz clic en AlloyDB Studio.
Inicia sesión en AlloyDB Studio con el nombre de tu base de datos, tu nombre de usuario y tu contraseña.
Define el GUC
enable_parallel_select_for_insert_select_into_part_tableenon.SET enable_parallel_select_for_insert_select_into_part_table = on;Después de habilitar el parámetro GUC, el planificador de consultas considera automáticamente los planes paralelos para las instrucciones
INSERT INTO ... SELECTen las que el destino es una tabla particionada, siempre que se determine que la consulta es segura para el paralelismo.En el siguiente ejemplo se obtiene un plan EXPLAIN que muestra un nodo Gather, lo que indica que la
SELECTdesource_tablese ejecuta en paralelo.-- Create a partitioned table CREATE TABLE part_table (a INT, b TEXT) PARTITION BY RANGE (a); CREATE TABLE part_table_1 PARTITION OF part_table FOR VALUES FROM (MINVALUE) TO (1000); CREATE TABLE part_table_2 PARTITION OF part_table FOR VALUES FROM (1000) TO (MAXVALUE); -- Create a source table CREATE TABLE source_table (c1 INT, c2 TEXT); INSERT INTO source_table SELECT i, 'value_' || i FROM generate_series(1, 2000) i; ANALYZE source_table; -- Enable the feature SET enable_parallel_select_for_insert_select_into_part_table = on; -- Optional for parallelizing the query with a small amount of data SET parallel_setup_cost=0; SET parallel_tuple_cost=0; SET min_parallel_table_scan_size=0; -- Run the insert with a parallelizable select EXPLAIN INSERT INTO part_table SELECT * FROM source_table;Devuelve el siguiente resultado:
EXPLAIN (COSTS OFF) INSERT INTO part_table SELECT * FROM source_table; QUERY PLAN ----------------------------------------------- Insert on part_table -> Gather Workers Planned: 2 -> Parallel Seq Scan on source_table (4 rows)
Deshabilitar parámetros de ejecución paralela
Para inhabilitar los parámetros, sigue estos pasos:
En la Google Cloud consola, ve a la página Clusters.
Selecciona un clúster de la lista.
En el menú de navegación, haz clic en AlloyDB Studio.
Inicia sesión en AlloyDB Studio con el nombre de tu base de datos, tu nombre de usuario y tu contraseña.
Para inhabilitar el parámetro
enable_parallel_select_for_insert_select, ejecuta el siguiente comando SQL:SET enable_parallel_select_for_insert_select = OFF;Para inhabilitar el parámetro
enable_parallel_select_for_insert_select_into_part_table, ejecuta el siguiente comando SQL:SET enable_parallel_select_for_insert_select_into_part_table = OFF;
Verificar un plan paralelo
Para comprobar que el optimizador está usando un plan paralelo, utiliza el comando EXPLAIN. Busca un nodo Gather y los atributos Workers Planned o Workers Launched en el plan de consulta.
Ejemplo de tabla estándar
En el siguiente ejemplo de plan, se inician seis procesos de trabajo para una combinación hash paralela con el fin de ejecutar la instrucción SELECT.
EXPLAIN (ANALYZE)
INSERT INTO t1 SELECT t2.* FROM t1, t2 WHERE t1.c1 != t2.c1 AND t1.c2 = t2.c2;
QUERY PLAN
------------------------------------------------------------------------------------
Insert on t1 (cost=1209138.00..12801765.49 rows=0 width=0) (actual time=16812.677..19337.150 rows=0 loops=1)
-> Gather (cost=1209138.00..12801765.49 rows=99995407 width=24) (actual time=16812.674..19337.144 rows=0 loops=1)
Workers Planned: 6
Workers Launched: 6
-> Parallel Hash Join (...)
(...)
Ejemplo de tabla con particiones
En el siguiente ejemplo se muestra que, después de habilitar la función para las tablas particionadas, el plan muestra un nodo Gather con cuatro trabajadores planificados para SELECT.
-- First, enable the feature for partitioned tables
SET enable_parallel_select_for_insert_select_into_part_table = ON;
-- Then, explain the query
EXPLAIN (COSTS OFF) INSERT INTO part_table SELECT * FROM source_table;
QUERY PLAN
-----------------------------------------------
Insert on part_table
-> Gather
Workers Planned: 2
-> Parallel Seq Scan on source_table
(4 rows)