Hologres stocke les données des tables selon trois formats : orienté ligne, orienté colonne et hybride. Chaque format est optimisé pour des modèles de requête spécifiques. Sélectionnez le format lors de la création d'une table ; toute modification ultérieure nécessite de recréer la table.
Choisir un format de stockage
Utilisez ce tableau pour identifier le format adapté à votre charge de travail. Le format orienté colonne est celui par défaut.
| Orienté colonne | Orienté ligne | Hybride | |
|---|---|---|---|
| Idéal pour | Charges de travail OLAP : requêtes complexes, jointures, analyses complètes, agrégations | Requêtes ponctuelles sur clé primaire (PK) à haut débit (QPS) | Tables nécessitant à la fois des requêtes ponctuelles sur PK et des analyses OLAP ; requêtes ponctuelles hors PK |
| Limite de colonnes | 300 | 3 000 | 300 |
| Index par défaut | Plusieurs index, dont des index bitmap pour les colonnes de type chaîne | Index de clé primaire uniquement | Index orientés ligne et colonne |
| Surcoût de stockage | Faible | Faible | Plus élevé (données stockées à la fois en format ligne et colonne) |
Valeur orientation |
column (par défaut) |
row |
row,column |
Le stockage hybride engendre un surcoût de stockage plus important, car chaque écriture s'applique simultanément aux copies orientées ligne et colonne. N'utilisez ce format que si une seule table a impérativement besoin de combiner des recherches par clé primaire et des requêtes analytiques.
Définir le format de stockage
Spécifiez la propriété orientation lors de la création d'une table.
À partir de la version V2.1 :
CREATE TABLE <table_name> (...) WITH (orientation = '[column | row | row,column]');
Toutes versions :
BEGIN;
CREATE TABLE <table_name> (...);
CALL set_table_property('<table_name>', 'orientation', '[column | row | row,column]');
COMMIT;
Fonctionnement
Ces trois formats diffèrent par la disposition des données sur le disque et par les index qu'ils génèrent. Ces caractéristiques déterminent l'efficacité des différents types de requête.
Le format orienté colonne stocke les valeurs de chaque colonne de manière contiguë. Une requête telle que SELECT SUM(revenue) FROM orders WHERE region = 'APAC' lit uniquement les colonnes revenue et region en ignorant toutes les autres. Cette approche réduit les opérations d'E/S pour les requêtes analytiques qui ne concernent qu'un sous-ensemble restreint de colonnes sur un grand nombre de lignes.
Le format orienté ligne stocke les valeurs de chaque ligne de manière contiguë. Une requête comme SELECT * FROM orders WHERE id = '1001' effectue une recherche unique via la clé primaire et récupère la ligne entière en une seule analyse. Ce procédé s'avère efficace lorsque vous avez besoin d'accéder immédiatement à toutes les colonnes d'une ligne spécifique.
Le format hybride conserve à la fois une copie orientée ligne et une copie orientée colonne pour chaque ligne. L'optimiseur de requêtes sélectionne la copie offrant les meilleures performances selon le plan d'exécution. Chaque opération d'écriture doit aboutir dans les deux copies avant que l'opération ne soit considérée comme terminée.
Orienté colonne
Les tables orientées colonne utilisent le format ORC. Les données sont encodées à l'aide d'algorithmes tels que l'encodage par longueur de suite (RLE) et l'encodage par dictionnaire, puis compressées avec Snappy, Zlib, Zstd ou LZ4. La couche de stockage construit également des index bitmap et utilise la matérialisation tardive pour réduire les lectures de données inutiles.
Lorsqu'une table orientée colonne possède une clé primaire (PK), le système génère un identifiant de ligne (RID) pour chaque ligne. Grâce à des index tels qu'une clé de distribution ou une clé de clustering définis sur les colonnes fréquemment interrogées, le moteur localise rapidement le shard et le fichier.
À partir de la version V2.1 :
CREATE TABLE public.tbl_col (
id TEXT NOT NULL,
name TEXT NOT NULL,
class TEXT NOT NULL,
in_time TIMESTAMPTZ NOT NULL,
PRIMARY KEY (id)
)
WITH (
orientation = 'column',
clustering_key = 'class',
bitmap_columns = 'name',
event_time_column = 'in_time'
);
SELECT * FROM public.tbl_col WHERE id = '3333';
SELECT id, class, name FROM public.tbl_col WHERE id < '3333' ORDER BY id;
Toutes versions :
BEGIN;
CREATE TABLE public.tbl_col (
id TEXT NOT NULL,
name TEXT NOT NULL,
class TEXT NOT NULL,
in_time TIMESTAMPTZ NOT NULL,
PRIMARY KEY (id)
);
CALL set_table_property('public.tbl_col', 'orientation', 'column');
CALL set_table_property('public.tbl_col', 'clustering_key', 'class');
CALL set_table_property('public.tbl_col', 'bitmap_columns', 'name');
CALL set_table_property('public.tbl_col', 'event_time_column', 'in_time');
COMMIT;
SELECT * FROM public.tbl_col WHERE id = '3333';
SELECT id, class, name FROM public.tbl_col WHERE id < '3333' ORDER BY id;

Orienté ligne
Les tables orientées ligne utilisent le format SST. Les données sont stockées dans des blocs compressés et triés par clé. La couche de stockage construit des index de type Block Index et Bloom Filter, tandis qu'un mécanisme de compactage en arrière-plan maintient l'organisation des fichiers pour des recherches par clé primaire efficaces.
Recommandation : définir uniquement la clé primaire
Lorsqu'une table orientée ligne dispose d'une clé primaire, le système définit automatiquement cette clé comme clé de distribution et clé de clustering, et génère un RID pour chaque ligne. Une requête ponctuelle basée sur la clé primaire n'analyse qu'un seul index de clé primaire pour récupérer toutes les colonnes.
Lors de la création d'une table orientée ligne, définissez uniquement la clé primaire. Le système configure automatiquement la clé de distribution et la clé de clustering.
À partir de la version V2.1 :
CREATE TABLE public.tbl_row (
id TEXT NOT NULL,
name TEXT NOT NULL,
class TEXT,
PRIMARY KEY (id)
)
WITH (
orientation = 'row',
clustering_key = 'id',
distribution_key = 'id'
);
-- PK-based point query
SELECT * FROM public.tbl_row WHERE id = '1111';
-- Multiple key lookup
SELECT * FROM public.tbl_row WHERE id IN ('1111', '2222', '3333');
Toutes versions :
BEGIN;
CREATE TABLE public.tbl_row (
id TEXT NOT NULL,
name TEXT NOT NULL,
class TEXT,
PRIMARY KEY (id)
);
CALL set_table_property('public.tbl_row', 'orientation', 'row');
CALL set_table_property('public.tbl_row', 'clustering_key', 'id');
CALL set_table_property('public.tbl_row', 'distribution_key', 'id');
COMMIT;
-- PK-based point query
SELECT * FROM public.tbl_row WHERE id = '1111';
-- Multiple key lookup
SELECT * FROM public.tbl_row WHERE id IN ('1111', '2222', '3333');

Non recommandé : inadéquation entre la clé primaire et la clé de clustering
Si vous définissez des champs différents pour la clé primaire et la clé de clustering, chaque requête basée sur la clé primaire nécessite deux analyses :
Utilisez l'index de clé primaire pour localiser la valeur de la clé de clustering et le RID.
Utilisez la clé de clustering et le RID pour récupérer la ligne complète.
Ce schéma de double analyse réduit considérablement les performances des requêtes.
À partir de la version V2.1 :
-- Avoid: clustering_key differs from PK
CREATE TABLE public.tbl_row (
id TEXT NOT NULL,
name TEXT NOT NULL,
class TEXT,
PRIMARY KEY (id)
)
WITH (
orientation = 'row',
clustering_key = 'name', -- different from PK (id)
distribution_key = 'id'
);
Toutes versions :
BEGIN;
CREATE TABLE public.tbl_row (
id TEXT NOT NULL,
name TEXT NOT NULL,
class TEXT,
PRIMARY KEY (id)
);
CALL set_table_property('public.tbl_row', 'orientation', 'row');
CALL set_table_property('public.tbl_row', 'clustering_key', 'name'); -- different from PK (id)
CALL set_table_property('public.tbl_row', 'distribution_key', 'id');
COMMIT;

Hybride
Le stockage hybride (introduit dans la version V1.1) conserve les données simultanément en formats orienté ligne et orienté colonne. Une clé primaire est obligatoire. Chaque écriture s'effectue de manière atomique : l'opération réussit uniquement après l'écriture dans les deux copies.
Lors des requêtes, l'optimiseur sélectionne le format offrant la meilleure efficacité :
Requêtes ponctuelles sur clé primaire (
SELECT * FROM tbl WHERE pk = xxx) et scénarios Fixed Plan : chemin orienté ligne.Requêtes ponctuelles hors clé primaire (
SELECT * FROM tbl WHERE col1 = xx AND col2 = yyy) : l'optimiseur lit d'abord les lignes correspondantes depuis la copie orientée colonne, puis récupère les lignes complètes depuis la copie orientée ligne à l'aide des valeurs de clé retrouvées. Cette méthode évite les analyses complètes de table tout en renvoyant toutes les colonnes.Requêtes générales : chemin orienté colonne.
À partir de la version V2.1 :
CREATE TABLE public.tbl_row_col (
id TEXT NOT NULL,
name TEXT NOT NULL,
class TEXT NOT NULL,
PRIMARY KEY (id)
)
WITH (
orientation = 'row,column',
distribution_key = 'id',
clustering_key = 'class',
bitmap_columns = 'name'
);
SELECT * FROM public.tbl_row_col WHERE id = '2222'; -- PK point query
SELECT * FROM public.tbl_row_col WHERE class = 'Class Two'; -- Non-PK point query
SELECT * FROM public.tbl_row_col WHERE id = '2222' AND class = 'Class Two'; -- General OLAP query
Toutes versions :
BEGIN;
CREATE TABLE public.tbl_row_col (
id TEXT NOT NULL,
name TEXT NOT NULL,
class TEXT,
PRIMARY KEY (id)
);
CALL set_table_property('public.tbl_row_col', 'orientation', 'row,column');
CALL set_table_property('public.tbl_row_col', 'distribution_key', 'id');
CALL set_table_property('public.tbl_row_col', 'clustering_key', 'class');
CALL set_table_property('public.tbl_row_col', 'bitmap_columns', 'name');
COMMIT;
SELECT * FROM public.tbl_row_col WHERE id = '2222'; -- PK point query
SELECT * FROM public.tbl_row_col WHERE class = 'Class Two'; -- Non-PK point query
SELECT * FROM public.tbl_row_col WHERE id = '2222' AND class = 'Class Two'; -- General OLAP query

Exemples d'utilisation
Les exemples suivants utilisent la syntaxe WITH (orientation = ...) disponible à partir de la version V2.1. Pour la syntaxe équivalente set_table_property compatible avec toutes les versions, reportez-vous aux sections précédentes.
-- Column-oriented table (default)
CREATE TABLE tbl_col (
a INT NOT NULL,
b TEXT NOT NULL
)
WITH (
orientation = 'column'
);
-- Row-oriented table
CREATE TABLE public.tbl_row (
a INTEGER NOT NULL,
b TEXT NOT NULL,
PRIMARY KEY (a)
)
WITH (
orientation = 'row'
);
-- Hybrid table (row + column)
CREATE TABLE tbl_col_row (
pk TEXT NOT NULL,
col1 TEXT,
col2 TEXT,
col3 TEXT,
PRIMARY KEY (pk)
)
WITH (
orientation = 'row,column'
);
FAQ
Si le stockage hybride prend en charge à la fois les requêtes ponctuelles sur clé primaire et les requêtes OLAP, pourquoi ne pas toujours l'utiliser ?
Le stockage hybride entraîne un surcoût de stockage plus élevé, car les données sont écrites deux fois : une fois au format ligne et une fois au format colonne. Utilisez le stockage hybride uniquement lorsqu'une même table a réellement besoin de combiner des recherches par clé primaire à haut débit (QPS) et des requêtes analytiques. Pour les tables dédiées exclusivement à l'OLAP, le stockage orienté colonne est plus efficace. Pour les tables servant uniquement aux recherches par clé primaire, le stockage orienté ligne permet d'éviter ce surcoût.
Puis-je modifier le format de stockage d'une table après sa création ?
Non. La conversion directe n'est pas prise en charge. Pour changer le format de stockage, vous devez recréer la table avec la nouvelle valeur orientation.
Pourquoi le stockage orienté ligne prend-il en charge plus de colonnes que le stockage orienté colonne ?
Les tables orientées colonne construisent plusieurs index par défaut, notamment des index bitmap pour les colonnes de type chaîne. À mesure que le nombre de colonnes augmente, ces index alourdissent le stockage et ralentissent les écritures. Les tables orientées ligne n'indexent que la clé primaire, ce qui réduit considérablement le coût par colonne.
Que se passe-t-il si une table orientée ligne dépasse 3 000 colonnes ou si une table orientée colonne dépasse 300 colonnes ?
Il s'agit de limites recommandées, non de limites absolues. Les dépasser dégrade les performances : les tables orientées colonne avec un grand nombre de colonnes subissent un surcoût de stockage des index et d'écriture élevé ; les tables orientées ligne avec un très grand nombre de colonnes voient leur taille de ligne augmenter, ce qui réduit le débit des requêtes ponctuelles. Respectez les limites recommandées pour vos environnements de production.
Étapes suivantes
Pour obtenir des conseils sur la combinaison du choix du format de stockage avec d'autres propriétés de table, telles que la clé de distribution, la clé de clustering et le partitionnement, en fonction de vos modèles de requête, consultez le Guide d'optimisation de la création de tables basé sur les scénarios.