Aprenda a ajustar las consultas de tablas internas en Hologres mediante el mantenimiento de estadísticas, la configuración de fragmentos, la optimización de uniones y agregaciones, y el diseño eficiente de esquemas de tablas.
Guía rápida de decisiones
|
Síntoma |
Causa probable |
Acción recomendada |
|
Uniones lentas en tablas internas grandes |
Estadísticas desactualizadas |
Ejecute ANALYZE en todas las tablas involucradas en la unión |
|
Las consultas examinan demasiadas filas para filtros de rango o igualdad |
Falta clustering_key, columnas bitmap o segment_key |
Agregue clustering_key para filtros de rango, bitmap_columns para filtros de igualdad o segment_key para rangos basados en tiempo |
|
Alta latencia en consultas puntuales |
Tipo de almacenamiento inadecuado o falta de clave primaria/índice |
Use almacenamiento por filas o híbrido y defina una clave primaria y un índice adecuados |
|
Agregaciones COUNT DISTINCT lentas |
Deduplicación exacta con uso intensivo de recursos |
Utilice APPROX_COUNT_DISTINCT o UNIQ y considere usar la clave distinct como clave de distribución |
|
Agregaciones GROUP BY lentas |
Redistribución de datos y sesgo de datos en claves GROUP BY |
Establezca las claves GROUP BY como claves de distribución cuando sea posible y corrija el sesgo de datos |
Mantenimiento de estadísticas
Statistics (por ejemplo, distribuciones de datos, filas, columnas) ayudan al optimizador a elegir planes de ejecución eficientes. Las estadísticas desactualizadas pueden provocar una selección deficiente del orden de unión y errores OOM.
Comprobar si las estadísticas están actualizadas
Ejecute EXPLAIN en su consulta y revise la estimación de rows para cada tabla.
Si una tabla grande muestra rows=1000 (el valor predeterminado), las estadísticas están desactualizadas.
Actualizar estadísticas
Ejecute ANALYZE en las tablas con estadísticas obsoletas:
analyze <tablename>;
Identificar cuándo actualizar estadísticas
Ejecute analyze <tablename> en los siguientes casos:
Después de importar datos.
Después de múltiples operaciones INSERT, UPDATE o DELETE.
Tanto para tablas internas como externas.
En tablas padre para tablas particionadas.
Si encuentra errores OOM durante uniones o consultas lentas, ejecute analyze <tablename> antes de importar datos.
Configuración del recuento de fragmentos
El recuento de fragmentos determina el paralelismo de las consultas. Muy pocos fragmentos limitan el paralelismo; demasiados aumentan la sobrecarga de inicio.
Entender el recuento predeterminado de fragmentos
Hologres establece un recuento predeterminado de fragmentos según las especificaciones de la instancia, aproximadamente igual a las CU de consulta disponibles. Después de escalar, las bases de datos existentes conservan su recuento original de fragmentos; solo las nuevas bases de datos utilizan el valor predeterminado actualizado.
Determinar cuándo ajustar el recuento de fragmentos
Después de escalar 5 veces o más: Cree un nuevo Table Group con un mayor recuento de fragmentos.
Para nuevas cargas de trabajo empresariales: Cree un nuevo Table Group con un recuento de fragmentos adecuado.
Cuando experimente problemas de paralelismo: Compruebe si el total de fragmentos supera el valor predeterminado recomendado.
El total de fragmentos en todos los Table Groups no debe exceder el recuento predeterminado de fragmentos de la instancia para lograr una utilización óptima de la CPU.
Optimización de consultas JOIN
Utilice los siguientes métodos para mejorar el rendimiento de las uniones.
Actualizar estadísticas para consultas de unión
Como se menciona en Maintain statistics, las estadísticas desactualizadas pueden provocar que la tabla más grande cree una tabla hash, lo que reduce la eficiencia de la unión. Ejecute ANALYZE para actualizar las estadísticas de la tabla.
Seleccionar claves de distribución para uniones locales
Las claves de distribución determinan cómo se distribuyen los datos entre los fragmentos. Una selección adecuada permite uniones locales y reduce la redistribución de datos.
Principios para seleccionar claves de distribución:
Utilice las columnas de unión como clave de distribución.
Utilice columnas presentes en cláusulas GROUP BY frecuentes.
Elija columnas con una distribución de datos uniforme y discreta.
Ejemplo: Cuando se unen tablas frecuentemente en una columna específica, establezca esa columna como clave de distribución para ambas tablas:
-- Create tables with matching distribution keys
BEGIN;
CREATE TABLE orders (order_id INT, customer_id INT, amount DECIMAL);
CALL set_table_property('orders', 'distribution_key', 'customer_id');
COMMIT;
BEGIN;
CREATE TABLE customers (id INT, name TEXT);
CALL set_table_property('customers', 'distribution_key', 'id');
COMMIT;
Con las claves de distribución correctas, el plan de ejecución no muestra el operador Redistribute Motion, lo que confirma que se realizan uniones locales.
Uso de Runtime Filter en uniones
A partir de la versión V2.0, Hologres aplica automáticamente Accelerate multi-table joins with runtime filters para uniones de tablas grandes y pequeñas, lo que reduce los datos examinados sin necesidad de configuración manual.
Ajustar algoritmos de orden de unión
En consultas que unen muchas tablas, el optimizador puede tardar demasiado en encontrar el orden de unión óptimo. Ajuste el algoritmo según sea necesario:
set optimizer_join_order = '<value>';
|
Algoritmo |
Caso de uso |
Compromiso |
|
exhaustive2 |
Predeterminado para la mayoría de las consultas |
Mejor plan, mayor costo de optimización |
|
greedy |
Más de 10 tablas |
Optimización más rápida, plan potencialmente subóptimo |
|
query |
SQL simple y bien ordenado |
Se ejecuta en el orden del SQL, menor costo de optimización |
Optimizar operadores Motion en uniones
Hologres utiliza operadores Motion para redistribuir datos entre fragmentos:
|
Tipo de Motion |
Descripción |
|
Redistribute Motion |
Redistribuye datos por hash o aleatoriamente. |
|
Broadcast Motion |
Copia datos a todos los fragmentos. |
|
Gather Motion |
Recopila datos en un solo fragmento. |
|
Forward Motion |
Transfiere datos entre fuentes externas y Hologres para consultas federadas. |
Revise los planes de ejecución en busca de operadores Motion costosos y ajuste el diseño de la tabla:
Operadores Motion que consumen mucho tiempo: Rediseñe la distribución.
Caracteres Motion ineficientes causados por estadísticas desactualizadas: Actualice las estadísticas con
analyze.Difusión de tablas pequeñas: Reduzca el recuento de fragmentos para optimizar la eficiencia de Broadcast Motion.
Optimización de agregaciones
Optimizar COUNT DISTINCT
Reemplace el COUNT DISTINCT exacto (intensivo en recursos) por APPROX_COUNT_DISTINCT (más rápido, tasa de error del 0.1% al 1%) cuando sea aceptable una ligera variación.
Reemplace COUNT DISTINCT por UNIQ (V1.3+).
-
Establezca una clave de distribución adecuada.
Utilice la clave de COUNT DISTINCT como clave de distribución para evitar la redistribución de datos entre fragmentos.
-
Actualice a V2.1+ para obtener optimizaciones integradas.
La versión V2.1+ incluye optimizaciones integradas para escenarios de COUNT DISTINCT, incluidos uno o más COUNT DISTINCT, sesgo de datos y consultas sin GROUP BY.
Forzar agregación de múltiples etapas
La agregación de múltiples etapas reduce la transferencia de datos al realizar primero agregaciones parciales dentro de cada fragmento:
set optimizer_force_multistage_agg = on;
Optimizar múltiples funciones de agregación en la misma columna
A partir de la versión V4.0, Hologres deduplica automáticamente funciones de agregación idénticas en la misma columna, lo que reduce la computación. Actualice a V4.0+ para utilizar esta optimización.
Ejemplo:
-- Create a test table.
CREATE TABLE tbl(x int4, y int4);
-- Insert test data.
INSERT INTO tbl VALUES (1,2), (null,200), (1000,null), (10000,20000);
-- Query data
SELECT
sum(x + 1),
sum(x + 2),
sum(x - 3),
sum(x - 4)
FROM
tbl;
El plan de consulta muestra que x es la única clave de agrupación.
Para deshabilitarlo:
-- Disable at the session level.
SET hg_experimental_remove_related_group_by_key = off;
-- Disable at the DB level.
ALTER DATABASE <database_name> SET hg_experimental_remove_related_group_by_key = off;
Optimización del esquema de tabla e índices
Elección de formatos de almacenamiento
Hologres admite almacenamiento por filas, por columnas e híbrido. Elija según su carga de trabajo:
|
Formato de almacenamiento |
Ideal para |
Compromiso |
|
Almacenamiento por filas |
Consultas puntuales por clave primaria, UPDATE/DELETE frecuentes |
Bajo rendimiento en exámenes de rango y agregaciones |
|
Almacenamiento por columnas |
Análisis, consultas multicolumna, agregaciones |
UPDATE/DELETE y consultas puntuales más lentos |
|
Almacenamiento híbrido fila-columna |
Cargas de trabajo mixtas |
Mayor sobrecarga de almacenamiento |
Elección de tipos de datos
Utilice tipos más pequeños siempre que sea posible (
INTen lugar deBIGINT).Especifique la precisión para los tipos
DECIMAL/NUMERIC.Evite
FLOAToDOUBLEpara columnas deGROUP BY.Utilice
TEXTpor su versatilidad. Minimice N al usarVARCHAR(N)oCHAR(N).Utilice
TIMESTAMPTZyDATEen lugar deTEXTpara fechas.Utilice tipos de datos consistentes en las condiciones de unión para evitar conversiones implícitas.
Diseño de una clave primaria
Las claves primarias garantizan la unicidad de los datos. Seleccione un método de deduplicación durante la importación:
ignore: Ignorar datos nuevos.
update: Sobrescribir datos antiguos.
Las claves primarias adecuadas mejoran los planes de ejecución, especialmente para consultas GROUP BY.
En el modo de almacenamiento por columnas, las claves primarias ralentizan las escrituras; el rendimiento suele ser 3 veces mayor sin ellas.
Uso de tablas particionadas
Hologres admite particionamiento de un solo nivel. Un particionamiento adecuado acelera las consultas, pero demasiadas particiones crean archivos pequeños y perjudican el rendimiento.
Cree particiones diarias para datos incrementales con el fin de aislar el almacenamiento y el acceso.
Escenarios aplicables:
Utilice DROP o TRUNCATE en particiones completas para obtener un mejor rendimiento que con DELETE y sin impacto en otras particiones.
Aísle los exámenes a particiones específicas o tablas secundarias.
Utilice tablas particionadas para importaciones periódicas en tiempo real. Por ejemplo, use la fecha como clave de partición. Sentencias de ejemplo:
begin;
create table insert_partition(c1 bigint not null, c2 boolean, c3 float not null, c4 text, c5 timestamptz not null) partition by list(c4);
call set_table_property('insert_partition', 'orientation', 'column');
commit;
create table insert_partition_child1 partition of insert_partition for values in('20190707');
create table insert_partition_child2 partition of insert_partition for values in('20190708');
create table insert_partition_child3 partition of insert_partition for values in('20190709');
select * from insert_partition where c4 >= '20190708';
select * from insert_partition_child3;
Elección de índices adecuados
Hologres proporciona varios tipos de índices. Defina los índices al crear la tabla:
|
Tipo |
Propósito |
Consulta de ejemplo |
|
clustering_key |
Consultas de rango y filtrado |
|
|
bitmap_columns |
Consultas de igualdad |
|
|
segment_key (también conocida como event_time_column) |
Filtrado basado en tiempo (nivel de archivo) Filtrado rápido a nivel de archivo antes de los índices bitmap o clustering. Sigue la coincidencia de prefijo más a la izquierda (generalmente 1 columna). Utilice la primera marca de tiempo no vacía como segment_key. |
|
Notas:
Las claves clustering y segment siguen el principio de coincidencia de prefijo más a la izquierda.
Los índices bitmap admiten consultas AND/OR en múltiples columnas.
Utilice primero
segment_keypara filtrado basado en tiempo, luegobitmap_columnspara igualdad oclustering_keypara consultas de rango.
Ejemplo:
BEGIN;
CREATE TABLE events (
event_id INT NOT NULL,
user_id INT NOT NULL,
event_time TIMESTAMPTZ NOT NULL,
event_type TEXT
);
CALL set_table_property('events', 'clustering_key', 'event_time');
CALL set_table_property('events', 'segment_key', 'event_time');
CALL set_table_property('events', 'bitmap_columns', 'user_id,event_type');
COMMIT;
bitmap_columns se puede agregar después de la creación de la tabla. clustering_key y segment_key deben especificarse durante la creación.
Verifique el uso de índices en una consulta ejecutando EXPLAIN:
EXPLAIN SELECT * FROM events WHERE event_time > '2026-01-01';
Deshabilitar la codificación de diccionario para columnas de caracteres
La codificación de diccionario acelera las comparaciones de cadenas, pero añade sobrecarga de codificación/decodificación. Deshabilítela para columnas donde el costo de comparación sea bajo:
BEGIN;
CREATE TABLE logs (id INT, message TEXT);
CALL set_table_property('logs', 'dictionary_encoding_columns', '');
COMMIT;
Optimización de sentencias SQL
Evitar SQL externo (Postgres) como NOT IN
Hologres utiliza HQE (Hologres Query Engine) para obtener el mejor rendimiento. Los operadores no compatibles recurren a PQE (Postgres Query Engine), que es más lento.
Comprobación de la recursión a PQE en los planes de ejecución:
EXPLAIN SELECT * FROM orders WHERE id NOT IN (SELECT id FROM cancelled_orders);
Si observa External SQL (Postgres), reescriba la consulta:
|
No compatible con HQE |
Rewrite to |
Ejemplo |
Notas |
|
|
|
|
N/A. |
|
|
|
|
regexp_split_to_table admite expresiones regulares. A partir de Hologres V2.0.4, HQE admite |
|
|
|
Reescribir como:
|
Algunas versiones V0.10 y anteriores no admiten substring. A partir de V1.3, HQE admite entradas sin expresiones regulares para substring. |
|
|
|
Reescribir como:
|
|
|
|
Eliminar |
Reescribir como:
|
N/A. |
|
|
|
Reescribir como:
|
Compatible con HQE a partir de Hologres V2.0. |
|
|
|
Reescribir como:
|
Compatible con HQE a partir de Hologres V2.0. |
Evitar consultas LIKE difusas
Evite búsquedas difusas como la operación LIKE, ya que no utilizan índices.
Optimizar consultas ORDER BY LIMIT**
A partir de la versión V1.3, Hologres admite Merge Sort para consultas ORDER BY ... LIMIT, lo que elimina operaciones de ordenamiento redundantes.
Optimizar consultas GROUP BY
Establezca la columna GROUP BY como clave de distribución para reducir la redistribución de datos.
-- If data is distributed based on the values in column a, runtime data redistribution is reduced, and the parallel computing capability of shards is fully utilized.
select a, count(1) from t1 group by a;
A partir de la versión V4.0, Hologres reescribe automáticamente columnas GROUP BY relacionadas para reducir fusiones (profundidad máxima de búsqueda: 5 niveles). Una cláusula como GROUP BY COL_A, ((COL_A + 1)), ((COL_A + 2)) se reescribe a GROUP BY COL_A. Ejemplo:
CREATE TABLE tbl (
a int,
b int,
c int
);
-- Query
SELECT
a,
a + 1 as a1,
a + 2 as a2,
sum(b)
FROM tbl
GROUP BY
a,
a1,
a2;
El plan de ejecución confirma la reescritura: la cláusula GROUP BY contiene únicamente la columna a.
QUERY PLAN
Gather (cost=0.00..5.00 rows=1 width=20)
-> Project (cost=0.00..5.00 rows=1 width=20)
-> HashAggregate (cost=0.00..5.00 rows=1 width=12)
Group Key: a
-> Redistribution (cost=0.00..5.00 rows=1 width=8)
Hash Key: a
-> Local Gather (cost=0.00..5.00 rows=1 width=8)
-> Seq Scan on tbl (cost=0.00..5.00 rows=1 width=8)
Query Queue: init_warehouse.default_queue
Optimizer: HQO version 4.0.0
Para deshabilitarlo:
-- Disable the feature at the session level.
SET hg_experimental_remove_related_group_by_key = off;
-- Disable the feature at the database level.
ALTER DATABASE <database_name> SET hg_experimental_remove_related_group_by_key = off;
Habilitar la reutilización de CTE
Cuando se hace referencia a un CTE varias veces, habilite la reutilización de CTE para evitar recálculos (V1.3+):
SET optimizer_cte_inlining=off;
La reutilización de CTE está deshabilitada de forma predeterminada. Habilítela manualmente mediante GUC.
La reutilización de CTE depende de Spill en la etapa Shuffle. Grandes volúmenes de datos pueden afectar el rendimiento debido a tasas de consumo variables.
Optimizar análisis Top-N
-
En escenarios OLAP, recuperar los primeros N registros dentro de un grupo es un requisito común. Por ejemplo, la siguiente consulta SQL recupera los dos primeros registros de la tabla
tdentro de cada particiónb, ordenados pora:CREATE TABLE t ( a int, b int ); INSERT INTO t VALUES (2, 1), (3, 1), (4, 1), (5, 2), (6, 2); SELECT * FROM ( SELECT a, b, row_number() OVER (PARTITION BY b ORDER BY a) AS rn FROM t) t1 WHERE rn <= 2;El resultado de la ejecución es el siguiente:
a b rn 5 2 1 6 2 2 2 1 1 3 1 2 -
A partir de Hologres V4.1, el operador
Partition Sortintroduce la cláusulaLIMITen laPartition, filtrando datos tempranamente durante la clasificación. Esto reduce la memoria para funciones de ventana comorow_numberyranken escenarios Top-N, disminuyendo el riesgo de OOM. Habilitado de forma predeterminada. Para deshabilitarlo:-- Disable the feature at the session level. SET hg_experimental_enable_hash_partitioned_sort_v2 = off; -- Disable the feature at the database level. ALTER DATABASE <database_name> SET hg_experimental_enable_hash_partitioned_sort_v2 = off;
Manejo del sesgo de datos
Una distribución desigual de datos ralentiza las consultas. Compruebe el recuento de filas por fragmento para detectar sesgos:
-- hg_shard_id is a built-in hidden column in each table that describes the shard where the corresponding row of data is located.
SELECT hg_shard_id, count(1) FROM t1 GROUP BY hg_shard_id;
Si algunos fragmentos tienen significativamente más filas que otros:
-
Cambie la
distribution_keya una columna con distribución de datos uniforme.ImportanteCambiar la clave de distribución requiere recrear la tabla y volver a importar los datos.
Si los datos tienen un sesgo inherente, optimice desde una perspectiva empresarial.
Deshabilitar la caché de resultados para pruebas
Hologres almacena en caché los resultados de las consultas de forma predeterminada. Deshabilite la caché al evaluar el rendimiento:
set hg_experimental_enable_result_cache = off;