Découvrez comment optimiser les requêtes sur les tables internes Hologres en maintenant les statistiques, en configurant les shards, en optimisant les jointures et les agrégations, et en concevant des schémas de table efficaces.
Guide de décision rapide
|
Symptôme |
Cause probable |
Action recommandée |
|
Jointures lentes sur de grandes tables internes |
Statistiques obsolètes |
Exécutez ANALYZE sur toutes les tables impliquées dans la jointure |
|
Les requêtes analysent trop de lignes pour les filtres de plage ou d'égalité |
Clé de clustering, colonnes bitmap ou clé de segment manquante |
Ajoutez une clustering_key pour les filtres de plage, des bitmap_columns pour les filtres d'égalité, ou une segment_key pour les plages temporelles |
|
Latence élevée pour les requêtes ponctuelles |
Type de stockage inadapté ou clé primaire/index manquant |
Utilisez le stockage par ligne ou hybride et définissez une clé primaire et un index appropriés |
|
Agrégations COUNT DISTINCT lentes |
Déduplication exacte gourmande en ressources |
Utilisez APPROX_COUNT_DISTINCT ou UNIQ, et envisagez d'utiliser la clé distincte comme clé de distribution |
|
Agrégations GROUP BY lentes |
Redistribution des données et déséquilibre des données sur les clés GROUP BY |
Définissez les clés GROUP BY comme clés de distribution lorsque cela est possible et corrigez le déséquilibre des données |
Maintenir les statistiques
Statistics (par exemple, distributions de données, nombre de lignes, colonnes) aident l'optimiseur à choisir des plans d'exécution efficaces. Des statistiques obsolètes peuvent entraîner une mauvaise sélection de l'ordre des jointures et des erreurs OOM (Out Of Memory).
Vérifier si les statistiques sont à jour
Exécutez EXPLAIN sur votre requête et vérifiez l'estimation rows pour chaque table.
Si une grande table affiche rows=1000 (la valeur par défaut), les statistiques sont obsolètes.
Mettre à jour les statistiques
Exécutez ANALYZE sur les tables dont les statistiques sont périmées :
analyze <tablename>;
Identifier quand mettre à jour les statistiques
Exécutez analyze <tablename> lorsque :
Après l'importation de données.
Après plusieurs opérations INSERT, UPDATE ou DELETE.
Pour les tables internes et les tables externes.
Sur les tables parentes pour les tables partitionnées.
Si vous rencontrez des erreurs OOM lors de jointures ou des requêtes lentes, exécutez analyze <tablename> avant d'importer les données.
Configurer le nombre de shards
Le nombre de shards détermine le parallélisme des requêtes. Trop peu de shards limitent le parallélisme ; un nombre excessif augmente la surcharge au démarrage.
Comprendre le nombre de shards par défaut
Hologres définit un nombre de shards par défaut basé sur les spécifications de l'instance, approximativement égal aux CUs de requête disponibles. Après un scaling, les bases de données existantes conservent leur nombre de shards d'origine — seules les nouvelles bases de données utilisent la nouvelle valeur par défaut.
Déterminer quand ajuster le nombre de shards
Après un scale-up d'un facteur 5 ou plus : Créez un nouveau Table Group avec un nombre de shards plus élevé.
Pour de nouvelles charges de travail métier : Créez un nouveau Table Group avec un nombre de shards approprié.
En cas de problèmes de parallélisme : Vérifiez si le nombre total de shards dépasse la valeur par défaut recommandée.
Le nombre total de shards dans tous les Table Groups ne doit pas dépasser le nombre de shards par défaut de l'instance pour une utilisation optimale du CPU.
Optimiser les requêtes JOIN
Utilisez les méthodes suivantes pour améliorer les performances des jointures.
Mettre à jour les statistiques pour les requêtes de jointure
Comme mentionné dans Maintenir les statistiques, des statistiques obsolètes peuvent amener la table la plus grande à créer une table de hachage, réduisant ainsi l'efficacité de la jointure. Exécutez ANALYZE pour mettre à jour les statistiques de la table.
Sélectionner les clés de distribution pour les jointures locales
Les clés de distribution déterminent la manière dont les données sont réparties entre les shards. Une sélection appropriée permet des jointures locales et réduit le brassage de données.
Principes de sélection des clés de distribution :
Utilisez les colonnes de jointure comme clé de distribution.
Utilisez les colonnes présentes dans les clauses GROUP BY fréquentes
Choisissez des colonnes ayant une distribution de données uniforme et discrète
Exemple : Lorsque vous joignez fréquemment des tables sur une colonne spécifique, définissez cette colonne comme clé de distribution pour les deux tables :
-- 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;
Avec des clés de distribution correctes, le plan d'exécution n'affiche aucun opérateur Redistribute Motion, confirmant ainsi les jointures locales.
Utiliser Runtime Filter dans les jointures
À partir de la V2.0, Hologres applique automatiquement Accelerate multi-table joins with runtime filters pour les jointures entre grandes et petites tables, réduisant ainsi le volume de données analysées sans configuration manuelle.
Ajuster les algorithmes d'ordre de jointure
Pour les requêtes joignant de nombreuses tables, l'optimiseur peut mettre trop de temps à trouver l'ordre de jointure optimal. Ajustez l'algorithme selon vos besoins :
set optimizer_join_order = '<value>';
|
Algorithme |
Cas d'utilisation |
Compromis |
|
exhaustive2 |
Valeur par défaut pour la plupart des requêtes |
Meilleur plan, coût d'optimisation le plus élevé |
|
greedy |
Plus de 10 tables |
Optimisation plus rapide, plan potentiellement sous-optimal |
|
query |
SQL simple et bien ordonné |
S'exécute dans l'ordre SQL, coût d'optimisation le plus faible |
Optimiser les opérateurs Motion dans les jointures
Hologres utilise des opérateurs Motion pour redistribuer les données entre les shards :
|
Type de Motion |
Description |
|
Redistribute Motion |
Brasse les données par hachage ou aléatoirement |
|
Broadcast Motion |
Copie les données vers tous les shards. |
|
Gather Motion |
Collecte les données vers un seul shard. |
|
Forward Motion |
Transfère les données entre des sources externes et Hologres pour les requêtes fédérées. |
Vérifiez les plans d'exécution pour identifier les opérateurs Motion coûteux et ajustez la conception de la table :
Opérateurs Motion chronophages : Redéfinissez la distribution.
Caractéristiques Motion inefficaces causées par des statistiques obsolètes : Actualisez les statistiques avec
analyze.Diffusion de petites tables : Réduisez le nombre de shards pour optimiser l'efficacité du Broadcast Motion.
Optimiser les agrégations
Optimiser COUNT DISTINCT
Remplacez COUNT DISTINCT exact (gourmand en ressources) par APPROX_COUNT_DISTINCT (plus rapide, taux d'erreur de 0,1 % à 1 %) lorsqu'une légère variance est acceptable.
Remplacez COUNT DISTINCT par UNIQ (V1.3+).
-
Définissez une clé de distribution appropriée
Utilisez la clé COUNT DISTINCT comme clé de distribution pour éviter le brassage de données entre les shards.
-
Mettez à niveau vers la V2.1+ pour bénéficier des optimisations intégrées
La V2.1+ inclut des optimisations intégrées pour les scénarios COUNT DISTINCT, y compris un ou plusieurs COUNT DISTINCT, le déséquilibre des données et les requêtes sans GROUP BY.
Forcer l'agrégation en plusieurs étapes
L'agrégation en plusieurs étapes réduit le transfert de données en effectuant d'abord des agrégations partielles au sein de chaque shard :
set optimizer_force_multistage_agg = on;
Optimiser plusieurs fonctions d'agrégation sur la même colonne
À partir de la V4.0, Hologres déduplique automatiquement les fonctions d'agrégation identiques sur la même colonne, réduisant ainsi le calcul. Mettez à niveau vers la V4.0+ pour utiliser cette optimisation.
Exemple :
-- 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;
Le plan de requête indique que x est la seule clé de groupe.
Pour désactiver :
-- 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;
Optimiser le schéma de table et les index
Choisir les formats de stockage
Hologres prend en charge le stockage par ligne, par colonne et hybride. Choisissez en fonction de votre charge de travail :
|
Format de stockage |
Idéal pour |
Compromis |
|
Stockage par ligne |
Requêtes ponctuelles par clé primaire, UPDATE/DELETE fréquents |
Mauvaises performances pour les analyses de plage et les agrégations |
|
Stockage par colonne |
Analytique, requêtes multi-colonnes, agrégations |
UPDATE/DELETE et requêtes ponctuelles plus lents |
|
Stockage hybride ligne-colonne |
Charges de travail mixtes |
Frais de stockage plus élevés |
Choisir les types de données
Utilisez des types plus petits lorsque cela est possible (
INTau lieu deBIGINT)Spécifiez la précision pour les types
DECIMAL/NUMERIC.Évitez
FLOATouDOUBLEpour les colonnesGROUP BY.Utilisez
TEXTpour sa polyvalence. Minimisez N lorsque vous utilisezVARCHAR(N)ouCHAR(N).Utilisez
TIMESTAMPTZetDATEau lieu deTEXTpour les dates.Utilisez des types de données cohérents dans les conditions de jointure pour éviter les conversions implicites
Concevoir une clé primaire
Les clés primaires garantissent l'unicité des données. Sélectionnez une méthode de déduplication lors de l'importation :
ignore : Ignorer les nouvelles données.
update : Écraser les anciennes données.
Des clés primaires appropriées améliorent les plans d'exécution, en particulier pour les requêtes GROUP BY.
En mode de stockage columnaire, les clés primaires ralentissent les écritures — le débit est généralement 3 fois plus élevé sans clé primaire.
Utiliser une table partitionnée
Hologres prend en charge le partitionnement à un seul niveau. Un partitionnement approprié accélère les requêtes, mais trop de partitions créent de petits fichiers et nuisent aux performances.
Créez des partitions quotidiennes pour les données incrémentielles afin d'isoler le stockage et l'accès.
Scénarios applicables :
DROP ou TRUNCATE des partitions entières pour de meilleures performances que DELETE et sans impact sur les autres partitions.
Isoler les analyses vers des partitions ou des tables enfants spécifiques.
Utiliser des tables partitionnées pour les importations en temps réel périodiques. Par exemple, utilisez la date comme clé de partition. Exemples d'instructions :
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;
Choisir des index appropriés
Hologres propose plusieurs types d'index. Définissez les index lors de la création de la table :
|
Type |
Objectif |
Exemple de requête |
|
clustering_key |
Requêtes de plage et filtrage |
|
|
bitmap_columns |
Requêtes d'égalité |
|
|
segment_key (également connu sous le nom de event_time_column) |
Filtrage basé sur le temps (niveau fichier) Filtrage rapide au niveau des fichiers avant les index bitmap ou de clustering. Suit la correspondance de préfixe gauche (généralement 1 colonne). Utilisez le premier horodatage non vide comme segment_key. |
|
Notes :
Les clés de clustering et de segment suivent le principe de correspondance de préfixe gauche.
Les index bitmap prennent en charge les requêtes AND/OR sur plusieurs colonnes.
Utilisez d'abord
segment_keypour le filtrage basé sur le temps, puisbitmap_columnspour l'égalité ouclustering_keypour les requêtes de plage.
Exemple :
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 peut être ajouté après la création de la table. clustering_key et segment_key doivent être spécifiés lors de la création.
Vérifiez l'utilisation des index dans une requête en exécutant EXPLAIN :
EXPLAIN SELECT * FROM events WHERE event_time > '2026-01-01';
Désactiver l'encodage par dictionnaire pour les colonnes de caractères
L'encodage par dictionnaire accélère les comparaisons de chaînes mais ajoute une surcharge d'encodage/décodage. Désactivez-le pour les colonnes où le coût de comparaison est faible :
BEGIN;
CREATE TABLE logs (id INT, message TEXT);
CALL set_table_property('logs', 'dictionary_encoding_columns', '');
COMMIT;
Optimiser les instructions SQL
Éviter le SQL externe (Postgres) tel que NOT IN
Hologres utilise HQE (Hologres Query Engine) pour de meilleures performances. Les opérateurs non pris en charge basculent vers PQE (Postgres Query Engine), qui est plus lent.
Vérification du basculement vers PQE dans les plans d'exécution :
EXPLAIN SELECT * FROM orders WHERE id NOT IN (SELECT id FROM cancelled_orders);
Si vous voyez External SQL (Postgres), réécrivez la requête :
|
Non pris en charge par HQE |
Réécrire en |
Exemple |
Notes |
|
|
|
|
N/A. |
|
|
|
|
regexp_split_to_table prend en charge les expressions régulières. À partir de Hologres V2.0.4, HQE prend en charge |
|
|
|
Réécrire en :
|
Certaines versions V0.10 et antérieures ne prennent pas en charge substring. À partir de la V1.3, HQE prend en charge les entrées non regex pour substring. |
|
|
|
Réécrire en :
|
|
|
|
Supprimer |
Réécrire en :
|
N/A. |
|
|
|
Réécrire en :
|
Pris en charge par HQE à partir de Hologres V2.0. |
|
|
|
Réécrire en :
|
Pris en charge par HQE à partir de Hologres V2.0. |
Éviter les requêtes floues LIKE
Évitez les recherches floues comme l'opération LIKE car elles n'utilisent pas les index.
Optimiser les requêtes ORDER BY LIMIT
À partir de la V1.3, Hologres prend en charge Merge Sort pour les requêtes ORDER BY ... LIMIT, éliminant ainsi les opérations de tri redondantes.
Optimiser les requêtes GROUP BY
Définissez la colonne GROUP BY comme clé de distribution pour réduire la redistribution des données.
-- 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;
À partir de la V4.0, Hologres réécrit automatiquement les colonnes GROUP BY connexes pour réduire les fusions (profondeur de recherche maximale : 5 niveaux). Une clause telle que GROUP BY COL_A, ((COL_A + 1)), ((COL_A + 2)) est réécrite en GROUP BY COL_A. Exemple :
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;
Le plan d'exécution confirme la réécriture — la clause GROUP BY ne contient que la colonne 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
Pour désactiver :
-- 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;
Activer la réutilisation des CTE
Lorsqu'un CTE est référencé plusieurs fois, activez la réutilisation des CTE pour éviter le recalcul (V1.3+) :
SET optimizer_cte_inlining=off;
La réutilisation des CTE est désactivée par défaut. Activez-la manuellement via GUC.
La réutilisation des CTE repose sur Spill dans l'étape Shuffle. De grands volumes de données peuvent affecter les performances en raison des taux de consommation variables.
Optimiser l'analyse Top-N
-
Dans les scénarios OLAP, la récupération des N premiers enregistrements au sein d'un groupe est une exigence courante. Par exemple, la requête SQL suivante récupère les deux premiers enregistrements de la table
tdans chaque partitionb, triés para: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;Le résultat d'exécution est le suivant :
a b rn 5 2 1 6 2 2 2 1 1 3 1 2 -
À partir de Hologres V4.1, l'opérateur
Partition Sortpousse la clauseLIMITdans laPartition, filtrant les données tôt pendant le tri. Cela réduit la mémoire nécessaire pour les fonctions de fenêtre commerow_numberetrankdans les scénarios Top-N, réduisant ainsi le risque d'OOM. Activé par défaut. Pour désactiver :-- 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;
Gérer le déséquilibre des données
Une distribution inégale des données ralentit les requêtes. Vérifiez le nombre de lignes par shard pour détecter le déséquilibre :
-- 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 certains shards ont significativement plus de lignes que d'autres :
-
Modifiez la
distribution_keyvers une colonne ayant une distribution de données uniforme.ImportantLa modification de la clé de distribution nécessite la recréation de la table et la réimportation des données.
Si les données sont intrinsèquement déséquilibrées, optimisez d'un point de vue métier
Désactiver la mise en cache des résultats pour les tests
Hologres met en cache les résultats de requête par défaut. Désactivez la mise en cache lors du benchmarking des performances :
set hg_experimental_enable_result_cache = off;