Optimización de subconsultas correlacionadas en Aurora PostgreSQL
Una subconsulta correlacionada hace referencia a las columnas de la tabla desde la consulta externa. Se evalúa una vez por cada fila devuelta por la consulta externa. En el siguiente ejemplo, la subconsulta hace referencia a una columna de la tabla ot. Esta tabla no está incluida en la cláusula FROM de la subconsulta, pero se hace referencia a ella en la cláusula FROM de la consulta externa. Si la tabla ot tiene 1 millón de filas, la subconsulta debe evaluarse 1 millón de veces.
SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT AVG(it.b) FROM it WHERE it.a = ot.a);
nota
-
La transformación de subconsultas y la caché de subconsultas están disponibles en Aurora PostgreSQL a partir de la versión 16.8, mientras que Babelfish para Aurora PostgreSQL admite estas características desde la versión 4.2.0.
-
A partir de las versiones 4.6.0 y 5.2.0 de Babelfish para Aurora PostgreSQL, estas características se controlan mediante los siguientes parámetros:
-
babelfishpg_tsql.apg_enable_correlated_scalar_transform
-
babelfishpg_tsql.apg_enable_subquery_cache
De forma predeterminada, ambos parámetros están activados.
-
Mejora del rendimiento de las consultas de Aurora PostgreSQL mediante la transformación de subconsultas
Aurora PostgreSQL puede acelerar las subconsultas correlacionadas transformándolas en uniones externas equivalentes. Esta optimización se aplica a los dos tipos siguientes de subconsultas correlacionadas:
-
Subconsultas que devuelven un único valor agregado y aparecen en la lista SELECT.
SELECT ot.a, ot.b, (SELECT AVG(it.b) FROM it WHERE it.a = ot.a) FROM ot; -
Subconsultas que devuelven un único valor agregado y aparecen en una cláusula WHERE.
SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT AVG(it.b) FROM it WHERE it.a = ot.a);
Habilitar la transformación en la subconsulta
Para habilitar la transformación de subconsultas correlacionadas en uniones externas equivalentes, defina el parámetro apg_enable_correlated_scalar_transform en ON. El valor predeterminado de este parámetro es OFF.
Puede modificar el grupo de parámetros de instancia o clúster para establecer los parámetros. Para obtener más información, consulte Grupos de parámetros para Amazon Aurora.
De forma alternativa, puede configurar los ajustes solo para la sesión actual mediante el siguiente comando:
SET apg_enable_correlated_scalar_transform TO ON;
Verificación de transformaciones
Utilice el comando EXPLAIN para comprobar si la subconsulta correlacionada se ha transformado en una combinación externa en el plan de consultas.
Cuando la transformación esté habilitada, la parte de la subconsulta correlacionada aplicable se transformará en una combinación externa. Por ejemplo:
postgres=> CREATE TABLE ot (a INT, b INT); CREATE TABLE postgres=> CREATE TABLE it (a INT, b INT); CREATE TABLE postgres=> SET apg_enable_correlated_scalar_transform TO ON; SET postgres=> EXPLAIN (COSTS FALSE) SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT AVG(it.b) FROM it WHERE it.a = ot.a);QUERY PLAN -------------------------------------------------------------- Hash Join Hash Cond: (ot.a = apg_scalar_subquery.scalar_output) Join Filter: ((ot.b)::numeric < apg_scalar_subquery.avg) -> Seq Scan on ot -> Hash -> Subquery Scan on apg_scalar_subquery -> HashAggregate Group Key: it.a -> Seq Scan on it
La misma consulta no se transforma cuando el parámetro GUC pasa a OFF. El plan no tendrá una combinación externa, sino un subplan.
postgres=> SET apg_enable_correlated_scalar_transform TO OFF; SET postgres=> EXPLAIN (COSTS FALSE) SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT AVG(it.b) FROM it WHERE it.a = ot.a);QUERY PLAN ---------------------------------------- Seq Scan on ot Filter: ((b)::numeric < (SubPlan 1)) SubPlan 1 -> Aggregate -> Seq Scan on it Filter: (a = ot.a)
Limitaciones
-
La subconsulta debe estar en la lista SELECT o en una de las condiciones de la cláusula WHERE. De lo contrario, no se transformará.
-
La subconsulta debe devolver una función agregada. Las funciones de agregado definidas por el usuario no se admiten para la transformación.
-
Una subconsulta cuya expresión de devolución no sea una simple función agregada no se transformará.
-
La condición correlacionada en las cláusulas WHERE de la subconsulta debe ser una referencia de columna simple. De lo contrario, no se transformará.
-
La condición correlacionada en las cláusulas WHERE de la subconsulta debe ser un predicado de igualdad simple.
-
La subconsulta no puede contener una cláusula HAVING o una cláusula GROUP BY.
-
La cláusula WHERE de la subconsulta puede contener uno o más predicados combinados con AND.
nota
El impacto de la transformación en el rendimiento varía según el esquema, los datos y la carga de trabajo. La ejecución de subconsultas correlacionada con la transformación puede mejorar significativamente el rendimiento a medida que aumenta el número de filas generadas por la consulta externa. Le recomendamos encarecidamente que pruebe esta característica en un entorno que no sea de producción con su esquema, datos y carga de trabajo reales antes de habilitarla en un entorno de producción.
Uso de la caché de subconsultas para mejorar el rendimiento de las consultas de Aurora PostgreSQL
Aurora PostgreSQL admite la caché de subconsultas para almacenar los resultados de las subconsultas correlacionadas. Esta característica omite las ejecuciones repetidas de subconsultas correlacionadas cuando los resultados de las subconsultas ya están en la memoria caché.
La caché de subconsultas
El nodo Memoize de PostgreSQL es la parte clave de la caché de subconsultas. El nodo Memoize mantiene una tabla hash en la caché local para hacer asignaciones desde los valores de los parámetros de entrada a las filas de resultados de las consultas. El límite de memoria de la tabla hash es el producto de work_mem y hash_mem_multiplier. Para obtener más información, consulte Resource Consumption
Durante la ejecución de la consulta, la caché de subconsultas utiliza la tasa de aciertos de caché (CHR) para estimar si la caché mejora el rendimiento de las consultas y para decidir, en el tiempo de ejecución de la consulta, si se debe seguir utilizando la caché. La CHR es la relación entre el número de visitas a caché y el número total de solicitudes. Por ejemplo, si una subconsulta correlacionada debe ejecutarse 100 veces y 70 de esos resultados de ejecución se pueden recuperar de la memoria caché, la CHR es 0,7.
Por cada número apg_subquery_cache_check_interval de errores de caché, se evalúan las ventajas de la caché de subconsultas comprobando si la CHR es mayor que apg_subquery_cache_hit_rate_threshold. De lo contrario, la caché se borrará de la memoria y la ejecución de la consulta volverá a la ejecución original (reejecución de subconsulta sin caché).
Parámetros que controlan el comportamiento de la caché de subconsultas
En la siguiente tabla se muestran los parámetros que controlan el comportamiento de la caché de subconsultas.
|
Parámetro |
Descripción |
Valor predeterminado |
Permitido |
|---|---|---|---|
apg_enable_subquery_cache |
Permite el uso de la memoria caché para subconsultas escalares correlacionadas. |
OFF |
ON, OFF |
apg_subquery_cache_check_interval |
Establece la frecuencia, en número de errores de caché, para evaluar la tasa de aciertos de caché de subconsultas. |
500 |
0–2147483647 |
apg_subquery_cache_hit_rate_threshold |
Establece el umbral de la tasa de aciertos de caché de subconsultas. |
0.3 |
0,0-1,0 |
nota
-
Los valores más altos de
apg_subquery_cache_check_intervalpueden mejorar la precisión de la estimación de los beneficios de la memoria caché según la CHR, pero aumentarán la sobrecarga de la memoria caché, ya que la CHR no se evaluará hasta que la tabla caché tenga un númeroapg_subquery_cache_check_intervalde filas. -
Los valores altos de
apg_subquery_cache_hit_rate_thresholdsugieren el abandono de la caché de subconsultas y la vuelta a la opción original (reejecución de subconsultas sin caché).
Puede modificar el grupo de parámetros de instancia o clúster para establecer los parámetros. Para obtener más información, consulte Grupos de parámetros para Amazon Aurora.
De forma alternativa, puede configurar los ajustes solo para la sesión actual mediante el siguiente comando:
SET apg_enable_subquery_cache TO ON;
Activación de la caché de subconsultas en Aurora PostgreSQL
Cuando la caché de subconsultas está habilitada, Aurora PostgreSQL aplica la caché para guardar los resultados de las subconsultas. El plan de consultas tendrá entonces un nodo Memoize en SubPlan.
Por ejemplo, la siguiente secuencia de comandos muestra el plan de ejecución de consultas estimado de una subconsulta correlacionada simple sin caché de subconsultas.
postgres=> SET apg_enable_subquery_cache TO OFF; SET postgres=> EXPLAIN (COSTS FALSE) SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT it.b FROM it WHERE it.a = ot.a);QUERY PLAN ------------------------------------ Seq Scan on ot Filter: (b < (SubPlan 1)) SubPlan 1 -> Seq Scan on it Filter: (a = ot.a)
Tras activar apg_enable_subquery_cache, el plan de consultas incluirá un nodo Memoize bajo el nodo SubPlan, lo que indica que la subconsulta planea usar la memoria caché.
postgres=> SET apg_enable_subquery_cache TO ON; SET postgres=> EXPLAIN (COSTS FALSE) SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT it.b FROM it WHERE it.a = ot.a);QUERY PLAN ------------------------------------ Seq Scan on ot Filter: (b < (SubPlan 1)) SubPlan 1 -> Memoize Cache Key: ot.a Cache Mode: binary -> Seq Scan on it Filter: (a = ot.a)
El plan de ejecución de consultas actual contiene más detalles de la caché de subconsultas, incluidos los aciertos y los errores de caché. El siguiente resultado muestra el plan real de ejecución de la consulta del ejemplo anterior tras insertar algunos valores en las tablas.
postgres=> EXPLAIN (COSTS FALSE, TIMING FALSE, ANALYZE TRUE) SELECT ot.a, ot.b FROM ot WHERE ot.b < (SELECT it.b FROM it WHERE it.a = ot.a);QUERY PLAN ----------------------------------------------------------------------------- Seq Scan on ot (actual rows=2 loops=1) Filter: (b < (SubPlan 1)) Rows Removed by Filter: 8 SubPlan 1 -> Memoize (actual rows=0 loops=10) Cache Key: ot.a Cache Mode: binary Hits: 4 Misses: 6 Evictions: 0 Overflows: 0 Memory Usage: 1kB -> Seq Scan on it (actual rows=0 loops=6) Filter: (a = ot.a) Rows Removed by Filter: 4
El número total de aciertos de caché es 4 y el número total de errores de caché es 6. Si el número total de aciertos y errores es inferior al número de bucles del nodo Memoize, la evaluación de la CHR no se ha aprobado, y la caché se ha borrado y abandonado en algún momento. A continuación, la ejecución de la subconsulta ha vuelto a la reejecución original sin caché.
Limitaciones
La caché de subconsultas no admite ciertos patrones de subconsultas correlacionadas. Estos tipos de consultas se ejecutarán sin caché, aunque la caché de subconsultas esté activada:
-
Subconsultas correlacionadas IN/EXISTS/ANY/ALL
-
Subconsultas correlacionadas que contienen funciones no deterministas.
-
Subconsultas correlacionadas que hacen referencia a columnas de tablas externas con tipos de datos que no admiten operaciones de hash o igualdad.
Mejora del rendimiento de las consultas de Aurora PostgreSQL mediante la transformación de ventanas de subconsultas
Aurora PostgreSQL puede acelerar las subconsultas agregadas correlacionadas transformándolas en funciones de ventana equivalentes. Esta optimización se aplica a las subconsultas correlacionadas escalares de una cláusula WHERE que comparan una expresión externa con un agregado, como el siguiente patrón de consulta:
SELECT o.id, o.amount FROM orders o, products p WHERE p.id = o.product_id AND o.amount < ( SELECT 0.2 * avg(o2.amount) FROM orders o2 WHERE o2.product_id = p.id );
La transformación es una reescritura por plan que solo cambia el plan de ejecución, no los resultados de la consulta.
nota
La transformación de ventanas de subconsultas están disponibles en Aurora PostgreSQL a partir de la versión 18.6, mientras que Babelfish para Aurora PostgreSQL admite estas características a partir de la versión 6.2.0. En Babelfish para Aurora PostgreSQL, la característica se controla mediante el parámetro babelfishpg_tsql.apg_enable_subquery_to_window_transform, que está activado ON de forma predeterminada.
Cuándo utilizar la transformación de la ventana de subconsultas
Considere la posibilidad de habilitar esta transformación si tiene consultas que coincidan con el patrón de autocorrelación: una fila exterior comparada con un agregado calculado en la misma tabla con una condición de correlación.
Esta transformación es complementaria a la transformación de subconsultas correlacionadas existente, que reescribe las subconsultas correlacionadas como uniones externas. En su lugar, la transformación de la ventana de subconsultas las reescribe como funciones de ventana. Las dos transformaciones cubren patrones diferentes:
-
La transformación de subconsulta correlacionada se aplica a las subconsultas de la lista SELECT y de la cláusula WHERE. La subconsulta debe devolver una función agregada, como
avg(x)ocount(*), sin ninguna expresión adyacente. -
La transformación de la ventana de subconsultas solo se aplica a las subconsultas de la cláusula WHERE que utilizan el patrón de autocorrelación, donde la tabla de la subconsulta también aparece en el FROM externo. Además, admite los casos en los que el agregado se combina con un factor constante (por ejemplo,
0.2 * avg(o2.amount)) que la transformación de la subconsulta correlacionada no puede gestionar.
Puede habilitar ambas transformaciones al mismo tiempo. Cuando una consulta cumple los requisitos para ambas, se aplica la transformación de la ventana de subconsultas; cuando solo cumple con los requisitos para una, se aplica esa transformación.
Habilitación de la transformación de la ventana de subconsultas
Para habilitar la transformación de subconsultas correlacionadas en funciones de ventanas, defina el parámetro apg_enable_subquery_to_window_transform en ON. El valor predeterminado de este parámetro es OFF.
Puede modificar el grupo de parámetros de instancia o clúster para establecer los parámetros. Para obtener más información, consulte Grupos de parámetros para Amazon Aurora.
De forma alternativa, puede configurar los ajustes solo para la sesión actual mediante el siguiente comando:
SET apg_enable_subquery_to_window_transform TO ON;
Para desactivar la transformación, establezca el parámetro en OFF con los mismos métodos. Los cambios se aplican sin necesidad de reiniciar la instancia; SET por sesión es inmediato y los cambios en los grupos de parámetros se aplican a las conexiones nuevas.
nota
En el caso de Babelfish para Aurora PostgreSQL, solo babelfishpg_tsql.apg_enable_subquery_to_window_transform controla si se aplica la transformación. El parámetro apg_enable_subquery_to_window_transform no tiene ningún efecto en el dialecto T-SQL.
Verificación de transformaciones
Utilice el comando EXPLAIN para comprobar si la subconsulta correlacionada se ha transformado en una función de ventana en el plan de consultas.
Cuando la transformación está habilitada, el plan de consulta contiene un nodo WindowAgg en lugar de un nodo SubPlan. Por ejemplo:
postgres=> SET apg_enable_subquery_to_window_transform TO ON; SET postgres=> EXPLAIN (COSTS FALSE) SELECT o.id, o.amount FROM orders o, products p WHERE p.id = o.product_id AND o.amount < ( SELECT 0.2 * avg(o2.amount) FROM orders o2 WHERE o2.product_id = p.id );QUERY PLAN ------------------------------------------------------ Subquery Scan on _sw Filter: (_sw.amount < (0.2 * _sw._w_agg_result)) -> WindowAgg Window: w1 AS (PARTITION BY o.product_id) -> Sort Sort Key: o.product_id -> Hash Join Hash Cond: (o.product_id = p.id) -> Seq Scan on orders o -> Hash -> Seq Scan on products p
La misma consulta no se transforma cuando el parámetro GUC pasa a OFF. El plan no tendrá un nodo WindowAgg, sino un SubPlan en su lugar.
postgres=> SET apg_enable_subquery_to_window_transform TO OFF; SET postgres=> EXPLAIN (COSTS FALSE) SELECT o.id, o.amount FROM orders o, products p WHERE p.id = o.product_id AND o.amount < ( SELECT 0.2 * avg(o2.amount) FROM orders o2 WHERE o2.product_id = p.id );QUERY PLAN --------------------------------------------- Hash Join Hash Cond: (o.product_id = p.id) Join Filter: (o.amount < (SubPlan 1)) -> Seq Scan on orders o -> Hash -> Seq Scan on products p SubPlan 1 -> Aggregate -> Seq Scan on orders o2 Filter: (product_id = p.id)
nota
Para Babelfish para Aurora PostgreSQL, utilice los siguientes comandos para verificar la transformación.
Para activar o desactivar la transformación dentro de una sesión:
SELECT set_config('babelfishpg_tsql.apg_enable_subquery_to_window_transform', 'true', false); SELECT set_config('babelfishpg_tsql.apg_enable_subquery_to_window_transform', 'false', false);
Para ver el plan de consulta:
SET BABELFISH_SHOWPLAN_ALL ON -- run your query SET BABELFISH_SHOWPLAN_ALL OFF
Limitaciones
Si una consulta no cumple estas condiciones, se ejecuta con su plan original; no se produce ningún error.
-
La transformación solo se aplica a una subconsulta escalar de la cláusula WHERE de la consulta externa. Las subconsultas de la lista SELECT y las subconsultas anidadas dentro de una condición OR no se transforman. AND es compatible con otros predicados.
-
La cláusula FROM de la subconsulta debe hacer referencia exactamente a una tabla y esa misma tabla debe aparecer exactamente una vez en la cláusula FROM de la consulta externa. Las referencias a través de una vista o un CTE no cuentan como la misma tabla.
-
La consulta externa solo debe usar combinaciones internas en todas partes. Las combinaciones externas, las referencias de LATERAL, los CTE, las funciones de ventana y los conjuntos de agrupamientos (CUBE, ROLLUP, GROUPING SETS) en cualquier parte de la consulta externa la descalifican.
-
El objetivo de la subconsulta debe ser un agregado integrado compatible (SUM, COUNT, AVG, MIN o MAX), combinado opcionalmente con constantes literales (por ejemplo,
0.2 * avg(o2.amount)). No se admiten los agregados ordenados y definidos por el usuario, como ARRAY_AGG, STRING_AGG, JSON_AGG y PERCENTILE_CONT. -
El predicado correlacionado debe ser una igualdad simple (=) entre referencias de columnas simples en ambos lados. Se permiten las claves compuestas (múltiples igualdades de AND) siempre que todas las columnas del lado exterior pertenezcan a la misma tabla exterior. Los predicados no correlacionados adicionales de la tabla de subconsultas se pueden combinar con AND.
-
La subconsulta no puede contener una cláusula GROUP BY, HAVING, LIMIT, ORDER BY, DISTINCT o FOR UPDATE; operaciones de conjunto (UNION, INTERSECT, EXCEPT); funciones de devolución de conjuntos; funciones de ventana; CTE; subconsultas anidadas; ni funciones volátiles como
random()oclock_timestamp(). -
La unión entre la tabla correlacionada y cualquier otra tabla externa debe realizarse en una columna con una clave principal o una restricción única, de modo que, como máximo, una fila de la otra tabla externa coincida con cada fila de la tabla correlacionada.
nota
El impacto de la transformación en el rendimiento varía según el esquema, los datos y la carga de trabajo. La ejecución de subconsultas correlacionada con la transformación de funciones de ventana puede mejorar significativamente el rendimiento a medida que aumenta el número de filas generadas por la consulta externa. Le recomendamos encarecidamente que pruebe esta característica en un entorno que no sea de producción con su esquema, datos y carga de trabajo reales antes de habilitarla en un entorno de producción.