Skip to main content
Le moteur MergeTree et les autres moteurs de la famille MergeTree (par ex. ReplacingMergeTree, AggregatingMergeTree) sont les moteurs de table les plus couramment utilisés et les plus robustes dans ClickHouse. Les moteurs de table de la famille MergeTree sont conçus pour des taux d’ingestion de données élevés et de très gros volumes de données. Les opérations d’insertion créent des parties de table, qui sont fusionnées avec d’autres parties de table par un processus d’arrière-plan. Principales fonctionnalités des moteurs de table de la famille MergeTree.
  • La clé primaire de la table détermine l’ordre de tri au sein de chaque partie de table (index clusterisé). La clé primaire ne référence pas non plus des lignes individuelles, mais des blocs de 8192 lignes appelés granules. Cela rend les clés primaires de très gros jeux de données suffisamment petites pour rester chargées en mémoire vive, tout en offrant un accès rapide aux données sur disque.
  • Les tables peuvent être partitionnées à l’aide d’une expression de partition arbitraire. L’élagage des partitions garantit que certaines partitions ne sont pas lues lorsque la requête le permet.
  • Les données peuvent être répliquées sur plusieurs nœuds du cluster pour assurer la haute disponibilité, le failover et des mises à niveau sans interruption de service. Voir Réplication des données.
  • Les moteurs de table MergeTree prennent en charge différents types de statistiques et méthodes d’échantillonnage pour faciliter l’optimisation des requêtes.
Malgré un nom similaire, le moteur Merge est différent des moteurs *MergeTree.

Créer des tables

Pour une description détaillée des paramètres, consultez l’instruction CREATE TABLE

Clauses de requête

ENGINE

ENGINE — Nom et paramètres du moteur. ENGINE = MergeTree(). Le moteur MergeTree n’a pas de paramètres.

ORDER BY

ORDER BY — La clé de tri. Un tuple de noms de colonnes ou d’expressions arbitraires. Exemple : ORDER BY (CounterID + 1, EventDate). Si aucune clé primaire n’est définie (c.-à-d. si PRIMARY KEY n’a pas été spécifiée), ClickHouse utilise la clé de tri comme clé primaire. Si aucun tri n’est nécessaire, vous pouvez utiliser la syntaxe ORDER BY tuple(). Autrement, si le paramètre create_table_empty_primary_key_by_default est activé, ORDER BY () est ajouté implicitement aux instructions CREATE TABLE. Voir Sélection d’une clé primaire.

PARTITION BY

PARTITION BY — La clé de partitionnement. Facultatif. Dans la plupart des cas, vous n’avez pas besoin de clé de partitionnement, et si vous devez partitionner, il n’est généralement pas nécessaire d’utiliser une clé de partitionnement plus fine qu’un partitionnement mensuel. Le partitionnement n’accélère pas les requêtes (contrairement à l’expression ORDER BY). Vous ne devez jamais utiliser un partitionnement trop fin. Ne partitionnez pas vos données par identifiant ou nom de client (utilisez plutôt l’identifiant ou le nom du client comme première colonne de l’expression ORDER BY). Pour un partitionnement par mois, utilisez l’expression toYYYYMM(date_column), où date_column est une colonne de type Date. Les noms de partition ont ici le format "YYYYMM".

CLÉ PRIMAIRE

PRIMARY KEY — La clé primaire, si elle diffère de la clé de tri. Facultatif. La définition d’une clé de tri (à l’aide de la clause ORDER BY) définit implicitement une clé primaire. Il n’est généralement pas nécessaire de spécifier la clé primaire en plus de la clé de tri.

SAMPLE BY

SAMPLE BY — Une expression d’échantillonnage. Optionnel. Si elle est spécifiée, elle doit faire partie de la clé primaire. L’expression d’échantillonnage doit renvoyer un entier non signé. Exemple : SAMPLE BY intHash32(UserID) ORDER BY (CounterID, EventDate, intHash32(UserID)).

TTL

TTL — Une liste de règles qui spécifient la durée de conservation des lignes et la logique de déplacement automatique des parts entre les disques et les volumes. Facultatif. L’expression doit produire un Date ou un DateTime, par exemple TTL date + INTERVAL 1 DAY. Le type de règle DELETE|TO DISK 'xxx'|TO VOLUME 'xxx'|GROUP BY spécifie l’action à effectuer sur la part si l’expression est vérifiée (atteint l’heure actuelle) : suppression des lignes expirées, déplacement d’une part (si l’expression est vérifiée pour toutes les lignes d’une part) vers le disque spécifié (TO DISK 'xxx') ou vers le volume (TO VOLUME 'xxx'), ou agrégation des valeurs des lignes expirées. Le type de règle par défaut est la suppression (DELETE). Il est possible de spécifier plusieurs règles, mais il ne doit pas y avoir plus d’une règle DELETE. Pour plus de détails, voir TTL pour les colonnes et les tables

PARAMÈTRES

Voir Paramètres de MergeTree. Exemple de paramètre Sections
Dans l’exemple, nous définissons un partitionnement par mois. Nous définissons également une expression d’échantillonnage sous la forme d’un hash de l’ID utilisateur. Cela permet de répartir pseudo-aléatoirement les données de la table pour chaque CounterID et EventDate. Si vous définissez une clause SAMPLE lors de la sélection des données, ClickHouse renverra un échantillon de données pseudorandom uniforme pour un sous-ensemble d’utilisateurs. Le paramètre index_granularity peut être omis, car 8192 est la valeur par défaut.

Stockage des données

Une table se compose de parties de données triées par clé primaire. Lorsque des données sont insérées dans une table, des parties de données distinctes sont créées, et chacune d’elles est triée lexicographiquement par clé primaire. Par exemple, si la clé primaire est (CounterID, Date), les données de la partie sont triées par CounterID et, pour chaque CounterID, elles sont ordonnées par Date. Les données appartenant à des partitions différentes sont séparées dans des parties distinctes. En arrière-plan, ClickHouse fusionne les parties de données pour optimiser le stockage. Les parties appartenant à des partitions différentes ne sont pas fusionnées. Le mécanisme de fusion ne garantit pas que toutes les lignes ayant la même clé primaire se trouveront dans une seule et même partie de données. Les parties de données peuvent être stockées au format Wide ou Compact. Au format Wide, chaque colonne est stockée dans un fichier distinct du système de fichiers, tandis qu’au format Compact, toutes les colonnes sont stockées dans un seul fichier. Le format Compact peut être utilisé pour améliorer les performances des insertions petites et fréquentes. Le format de stockage des données est contrôlé par les paramètres min_bytes_for_wide_part et min_rows_for_wide_part du moteur de table. Si le nombre d’octets ou de lignes dans une partie de données est inférieur à la valeur du paramètre correspondant, la partie est stockée au format Compact. Sinon, elle est stockée au format Wide. Si aucun de ces paramètres n’est défini, les parties de données sont stockées au format Wide. Chaque partie de données est logiquement divisée en granules. Un granule est le plus petit ensemble de données indivisible que ClickHouse lit lors de la sélection de données. ClickHouse ne divise ni les lignes ni les valeurs, de sorte que chaque granule contient toujours un nombre entier de lignes. La première ligne d’un granule est marquée par la valeur de la clé primaire de cette ligne. Pour chaque partie de données, ClickHouse crée un fichier d’index qui stocke les marques. Pour chaque colonne, qu’elle fasse partie de la clé primaire ou non, ClickHouse stocke également les mêmes marques. Ces marques permettent de localiser directement les données dans les fichiers de colonnes. La taille du granule est limitée par les paramètres index_granularity et index_granularity_bytes du moteur de table. Le nombre de lignes dans un granule se situe dans l’intervalle [1, index_granularity], selon la taille des lignes. La taille d’un granule peut dépasser index_granularity_bytes si la taille d’une seule ligne est supérieure à la valeur du paramètre. Dans ce cas, la taille du granule est égale à celle de la ligne.

Clés primaires et index dans les requêtes

Prenons la clé primaire (CounterID, Date) comme exemple. Dans ce cas, l’ordre de tri et l’index se présentent comme suit :
Si la requête de données spécifie :
  • CounterID in ('a', 'h'), le serveur lit les données dans les plages de marques [0, 3) et [6, 8).
  • CounterID IN ('a', 'h') AND Date = 3, le serveur lit les données dans les plages de marques [1, 3) et [7, 8).
  • Date = 3, le serveur lit les données dans la plage de marques [1, 10].
Les exemples ci-dessus montrent qu’il est toujours plus efficace d’utiliser un index plutôt qu’un parcours complet. Un index épars permet de lire des données supplémentaires. Lors de la lecture d’une seule plage de la clé primaire, jusqu’à index_granularity * 2 lignes supplémentaires dans chaque bloc de données peuvent être lues. Les index épars permettent de travailler avec un très grand nombre de lignes de table, car dans la plupart des cas, ces index tiennent dans la RAM de l’ordinateur. ClickHouse n’exige pas de clé primaire unique. Vous pouvez insérer plusieurs lignes avec la même clé primaire. Vous pouvez utiliser des expressions de type Nullable dans les clauses PRIMARY KEY et ORDER BY, mais cela est fortement déconseillé. Pour autoriser cette fonctionnalité, activez le paramètre allow_nullable_key. Le principe NULLS_LAST s’applique aux valeurs NULL dans la clause ORDER BY.

Sélection d’une clé primaire

Le nombre de colonnes dans la clé primaire n’est pas explicitement limité. Selon la structure des données, vous pouvez inclure plus ou moins de colonnes dans la clé primaire. Cela peut :
  • Améliorer les performances d’un index. Si la clé primaire est (a, b), l’ajout d’une autre colonne c améliorera les performances si les conditions suivantes sont réunies :
    • Il existe des requêtes avec une condition sur la colonne c.
    • De longues plages de données (plusieurs fois plus longues que index_granularity) avec des valeurs identiques pour (a, b) sont fréquentes. En d’autres termes, l’ajout d’une colonne supplémentaire permet de sauter des plages de données assez longues.
  • Améliorer la compression. ClickHouse trie les données par clé primaire ; ainsi, plus la cohérence est élevée, meilleure est la compression.
  • Fournir une logique supplémentaire lors de la fusion des parties de données dans les moteurs CollapsingMergeTree et SummingMergeTree. Dans ce cas, il est judicieux de spécifier une clé de tri différente de la clé primaire.
Une clé primaire longue aura un impact négatif sur les performances d’insertion et la consommation de mémoire, mais les colonnes supplémentaires dans la clé primaire n’affectent pas les performances de ClickHouse lors des requêtes SELECT. Vous pouvez créer une table sans clé primaire en utilisant la syntaxe ORDER BY tuple(). Dans ce cas, ClickHouse stocke les données dans l’ordre d’insertion. Si vous souhaitez conserver l’ordre des données lors de l’insertion via des requêtes INSERT ... SELECT, définissez max_insert_threads = 1. Pour sélectionner les données dans leur ordre initial, utilisez des requêtes SELECT mono-thread.

Choisir une clé primaire différente de la clé de tri

Il est possible de définir une clé primaire (une expression dont les valeurs sont écrites dans le fichier d’index pour chaque marqueur) différente de la clé de tri (une expression utilisée pour trier les lignes dans les parties de données). Dans ce cas, le tuple d’expressions de la clé primaire doit être un préfixe du tuple d’expressions de la clé de tri. Cette fonctionnalité est utile avec les moteurs de table SummingMergeTree et AggregatingMergeTree. Dans le cas d’usage le plus courant de ces moteurs, la table comporte deux types de colonnes : les dimensions et les mesures. Les requêtes typiques agrègent les valeurs des colonnes de mesure avec des GROUP BY arbitraires et un filtrage sur les dimensions. Comme SummingMergeTree et AggregatingMergeTree agrègent les lignes ayant la même valeur de clé de tri, il est naturel d’y inclure toutes les dimensions. Par conséquent, l’expression de clé se compose d’une longue liste de colonnes, et cette liste doit être mise à jour fréquemment à mesure que de nouvelles dimensions sont ajoutées. Dans ce cas, il est judicieux de ne conserver dans la clé primaire que quelques colonnes permettant des lectures par plage efficaces, et d’ajouter les autres colonnes de dimension au tuple de la clé de tri. La modification de la clé de tri avec ALTER est une opération légère, car lorsqu’une nouvelle colonne est ajoutée simultanément à la table et à la clé de tri, les parties de données existantes n’ont pas besoin d’être modifiées. Comme l’ancienne clé de tri est un préfixe de la nouvelle et qu’il n’y a pas de données dans la colonne nouvellement ajoutée, les données sont triées à la fois selon l’ancienne et la nouvelle clé de tri au moment de la modification de la table.

Utilisation des index et des partitions dans les requêtes

Pour les requêtes SELECT, ClickHouse analyse si un index peut être utilisé. Un index peut être utilisé si la clause WHERE/PREWHERE contient une expression (comme l’un des termes de la conjonction, ou dans son intégralité) correspondant à une opération de comparaison d’égalité ou d’inégalité, ou si elle contient IN ou LIKE avec un préfixe fixe sur des colonnes ou des expressions faisant partie de la clé primaire ou de la clé de partitionnement, ou sur certaines fonctions partiellement répétitives de ces colonnes, ou encore sur des combinaisons logiques de ces expressions. Il est ainsi possible d’exécuter rapidement des requêtes sur un ou plusieurs intervalles de la clé primaire. Dans cet exemple, les requêtes seront rapides lorsqu’elles portent sur un tag de suivi spécifique, sur un tag spécifique et une plage de dates, sur un tag spécifique et une date, sur plusieurs tags avec une plage de dates, etc. Examinons le moteur configuré comme suit :
Dans ce cas, pour les requêtes :
ClickHouse utilisera l’index de clé primaire pour écarter les données non pertinentes, ainsi que la clé de partitionnement mensuelle pour exclure les partitions dont les dates se situent hors de l’intervalle recherché. Les requêtes ci-dessus montrent que l’index est utilisé même pour des expressions complexes. La lecture de la table est organisée de telle sorte que l’utilisation de l’index ne peut pas être plus lente qu’un parcours complet. Dans l’exemple ci-dessous, l’index ne peut pas être utilisé.
Pour vérifier si ClickHouse peut utiliser l’index lors de l’exécution d’une requête, utilisez les paramètres force_index_by_date et force_primary_key. La clé de partitionnement par mois permet de lire uniquement les blocs de données qui contiennent des dates dans la plage voulue. Dans ce cas, le bloc de données peut contenir des données correspondant à de nombreuses dates (jusqu’à un mois entier). Dans un bloc, les données sont triées par clé primaire, qui peut ne pas contenir la date en première colonne. C’est pourquoi une requête ne comportant qu’une condition sur la date, sans préciser le préfixe de la clé primaire, entraînera la lecture de plus de données que pour une date unique.

Utilisation de l’index avec des expressions déterministes dans les clés primaires

La clé primaire peut contenir des expressions, et pas seulement des noms de colonnes. Ces expressions ne se limitent pas à de simples chaînes de fonctions : il peut s’agir d’arbres d’expressions arbitraires (par exemple, des fonctions imbriquées et des expressions composées), à condition qu’elles soient déterministes. Une expression est déterministe si elle renvoie toujours le même résultat pour les mêmes valeurs d’entrée (par exemple : length(), toDate(), lower(), left(), cityHash64(), toUUID() ; contrairement à now() ou rand()). Si la clé primaire contient des expressions déterministes, ClickHouse peut les appliquer aux valeurs constantes de la requête et utiliser le résultat pour construire des conditions sur l’index de clé primaire. Cela permet d’ignorer des données pour des prédicats comme =, IN et has. Un cas d’utilisation courant consiste à garder la clé primaire compacte (par exemple, stocker un hash au lieu d’une longue String), tout en permettant à des prédicats sur la colonne d’origine d’utiliser l’index. Exemple de clé primaire déterministe (mais non injective) :
Exemples de prédicats pouvant utiliser l’index :
Dans ces cas, ClickHouse calcule length('alice') (et les autres constantes) une seule fois et utilise les valeurs de longueur pour restreindre les intervalles dans l’index de clé primaire. Comme la longueur d’une chaîne n’est pas injective, différentes chaînes user_id peuvent avoir la même longueur, si bien que l’index peut lire des granules supplémentaires (faux positifs). Le résultat reste correct, car le prédicat d’origine (user_id = ..., IN, etc.) est toujours appliqué après la lecture. Si l’expression déterministe est aussi injective (des entrées différentes ne peuvent pas produire la même sortie pour les types d’argument utilisés), ClickHouse peut en outre utiliser efficacement l’index pour les formes niées : !=, NOT IN et NOT has(...). Par exemple, reverse(p) et hex(p) sont injectives pour String. Exemple de clé primaire injective :
Des expressions injectives plus complexes sont elles aussi prises en charge, par exemple :
Exemples de prédicats pouvant utiliser l’index :

Utilisation de l’index pour les clés primaires partiellement monotones

Prenons, par exemple, les jours du mois. Ils forment une suite monotone sur un mois, mais ne le sont plus sur des périodes plus longues. Il s’agit d’une suite partiellement monotone. Si un utilisateur crée une table avec une clé primaire partiellement monotone, ClickHouse crée un index épars comme d’habitude. Lorsqu’un utilisateur sélectionne des données dans ce type de table, ClickHouse analyse les conditions de la requête. Si l’utilisateur veut obtenir des données entre deux marques de l’index et que ces deux marques se situent dans le même mois, ClickHouse peut utiliser l’index dans ce cas précis, car il peut calculer la distance entre les paramètres d’une requête et les marques de l’index. ClickHouse ne peut pas utiliser l’index si les valeurs de la clé primaire dans la plage des paramètres de la requête ne représentent pas une suite monotone. Dans ce cas, ClickHouse effectue une analyse complète. ClickHouse applique cette logique non seulement aux suites de jours du mois, mais aussi à toute clé primaire représentant une suite partiellement monotone.

Index de saut de données

La déclaration de l’index se trouve dans la section des colonnes de la requête CREATE.
Pour les tables de la famille *MergeTree, des index de saut de données peuvent être spécifiés. Ces index agrègent certaines informations sur l’expression spécifiée dans des blocs composés de granularity_value granules (la taille d’un granule est spécifiée à l’aide du paramètre index_granularity dans le moteur de table). Ces agrégats sont ensuite utilisés dans les requêtes SELECT afin de réduire la quantité de données à lire sur le disque en sautant de grands blocs de données pour lesquels la condition where ne peut pas être satisfaite. La clause GRANULARITY peut être omise, la valeur par défaut de granularity_value est 1. Exemple
Les index de l’exemple peuvent être utilisés par ClickHouse pour réduire la quantité de données à lire sur le disque dans les requêtes suivantes :
Les index de saut de données peuvent également être créés sur des colonnes composites :

Types de skip indexes

Le moteur de table MergeTree prend en charge les types de skip indexes suivants. Pour en savoir plus sur l’utilisation des skip indexes pour optimiser les performances, consultez “Comprendre les index de saut de données de ClickHouse”.

Index de saut MinMax

Pour chaque granule d’index, les valeurs minimale et maximale d’une expression sont stockées. (Si l’expression est de type tuple, les valeurs minimale et maximale de chaque élément du tuple sont stockées.)
Syntax

Set

Pour chaque granule d’index, jusqu’à max_rows valeurs uniques de l’expression spécifiée sont stockées. max_rows = 0 signifie “stocker toutes les valeurs uniques”.
Syntax

Filtre de Bloom

Pour chaque granule d’index, un filtre de Bloom est stocké pour les colonnes spécifiées.
Syntax
Le paramètre false_positive_rate peut prendre une valeur comprise entre 0 et 1 (par défaut : 0.025) et indique la probabilité de générer un résultat positif (ce qui augmente la quantité de données à lire). Les types de données suivants sont pris en charge :
  • (U)Int*
  • Float*
  • Enum
  • Date
  • DateTime
  • String
  • FixedString
  • Array
  • LowCardinality
  • Nullable
  • UUID
  • Map
Type de données Map : spécifier la création d’un index sur les clés ou les valeursPour le type de données Map, le client peut indiquer si l’index doit être créé sur les clés ou sur les valeurs à l’aide des fonctions mapKeys ou mapValues.
Type de données JSON : indexation des chemins JSONPour le type de données JSON, un index de type bloom filter peut être créé sur l’ensemble des chemins à l’aide de la fonction JSONAllPaths. Cela permet d’ignorer les granules dans lesquelles un chemin JSON interrogé est absent. Voir les index de saut de données pour JSON pour plus de détails.

Filtre de Bloom par n-grammes (Obsolète)

À partir de ClickHouse 26.2, avec la disponibilité générale (GA) de l’index text, l’index ngrambf_v1 n’est plus recommandé pour la recherche en texte intégral.Voir la page “Recherche en texte intégral avec les index de texte” pour plus de détails.
Pour chaque granule d’index, un filtre de Bloom est stocké pour les n-grammes des colonnes spécifiées.
Syntax
Cet index fonctionne uniquement avec les types de données suivants : Pour estimer les paramètres de ngrambf_v1, vous pouvez utiliser les fonctions définies par l’utilisateur (UDFs).
UDFs for ngrambf_v1
Pour utiliser ces fonctions, vous devez spécifier au moins deux paramètres :
  • total_number_of_all_grams
  • probability_of_false_positives
Par exemple, il y a 4300 ngrams dans le granule et vous souhaitez que les faux positifs restent inférieurs à 0.0001. Les autres paramètres peuvent ensuite être estimés en exécutant les requêtes suivantes :
Bien sûr, vous pouvez également utiliser ces fonctions pour estimer les paramètres d’autres conditions. Les fonctions ci-dessus s’appuient sur le calculateur de filtre de Bloom disponible ici.

Filtre de Bloom de jetons

Avec la disponibilité générale (GA) de l’index text à partir de la version 26.2 de ClickHouse, l’index tokenbf_v1 n’est plus recommandé pour la recherche en texte intégral.Voir la page “Recherche en texte intégral avec des index de texte” pour plus de détails.
Syntax

Filtre de Bloom de sparse grams

Le filtre de Bloom de sparse grams est similaire à ngrambf_v1, mais utilise des tokens sparse grams au lieu de ngrams.
Syntax

Index de texte

Crée un index inversé sur des données textuelles tokenisées, permettant une recherche en texte intégral efficace et déterministe. Voir ici pour plus de détails.

Similarité vectorielle

Prend en charge la recherche approximative des plus proches voisins ; voir ici pour plus de détails.

Prise en charge des fonctions

Les conditions de la clause WHERE contiennent des appels à des fonctions qui s’appliquent aux colonnes. Si la colonne fait partie d’un index, ClickHouse essaie d’utiliser cet index lors de l’évaluation des fonctions. ClickHouse prend en charge différents sous-ensembles de fonctions pour l’utilisation des index. Les index de type set peuvent être utilisés par toutes les fonctions. Les autres types d’index sont pris en charge comme suit : Les fonctions avec un argument constant inférieur à la taille du ngram ne peuvent pas être utilisées par ngrambf_v1 pour l’optimisation des requêtes. (*) Pour que hasTokenCaseInsensitive et hasTokenCaseInsensitiveOrNull soient efficaces, l’index tokenbf_v1 doit être créé sur des données converties en minuscules, par exemple INDEX idx (lower(str_col)) TYPE tokenbf_v1(512, 3, 0).
Les filtres de Bloom peuvent produire des faux positifs. Les index ngrambf_v1, tokenbf_v1, sparse_grams et bloom_filter ne peuvent donc pas être utilisés pour optimiser les requêtes lorsque le résultat attendu d’une fonction est faux.Par exemple :
  • Peut être optimisé :
    • s LIKE '%test%'
    • NOT s NOT LIKE '%test%'
    • s = 1
    • NOT s != 1
    • startsWith(s, 'test')
  • Ne peut pas être optimisé :
    • NOT s LIKE '%test%'
    • s NOT LIKE '%test%'
    • NOT s = 1
    • s != 1
    • NOT startsWith(s, 'test')

Projections

Les projections s’apparentent aux vues matérialisées, mais sont définies au niveau des parts. Elles garantissent la cohérence et sont utilisées automatiquement dans les requêtes.
Lorsque vous implémentez des projections, vous devez également prendre en compte le paramètre force_optimize_projection.
Les projections ne sont pas prises en charge dans les instructions SELECT utilisant le modificateur FINAL.

Requête de projection

C’est la requête de projection qui définit une projection. Elle sélectionne implicitement les données de la table parente. Syntaxe
Les projections peuvent être modifiées ou supprimées à l’aide de l’instruction ALTER.

Index de projection

Les index de projection étendent le sous-système des projections en fournissant un moyen léger et explicite de définir des index au niveau de la projection. Vu de l’extérieur, un index de projection reste une projection, mais avec une syntaxe simplifiée et une intention plus claire : il définit une expression dédiée au filtrage, plutôt qu’au service de données matérialisées. En interne, un index de projection ne matérialise pas la table d’origine dans un ordre de lignes permuté, contrairement à une projection classique. À la place, la permutation est stockée sous la forme d’une colonne numérique de permutation _part_offset, c.-à-d. SELECT _part_offset ORDER BY <index_expr>.

Syntaxe

Exemple :

Types d’index

Actuellement pris en charge :
  • basic : équivalent à un index MergeTree standard sur l’expression.
Le framework permettra d’ajouter d’autres types d’index à l’avenir.

Stockage des projections

Les projections sont stockées dans le répertoire de la part. C’est similaire à un index, mais avec un sous-répertoire qui stocke la part d’une table MergeTree anonyme. La table est déduite de la requête de définition de la projection. S’il y a une clause GROUP BY, le moteur de stockage sous-jacent devient AggregatingMergeTree, et toutes les fonctions d’agrégation sont converties en AggregateFunction. S’il y a une clause ORDER BY, la table MergeTree l’utilise comme expression de clé primaire. Lors du merge process, la projection part est fusionnée au moyen de la routine de fusion de son stockage. La checksum de la part de la table parent est combinée avec celle de la projection. Les autres tâches de maintenance sont similaires à celles des index de saut.

Analyse de requête

  1. Vérifiez si la projection peut être utilisée pour répondre à la requête donnée, c’est-à-dire si elle produit le même résultat qu’une requête sur la table de base.
  2. Sélectionnez la meilleure correspondance possible, c’est-à-dire celle qui contient le moins de granules à lire.
  3. Le pipeline de requête qui utilise des projections sera différent de celui qui utilise les parts d’origine. Si la projection est absente dans certaines parts, nous pouvons ajouter le pipeline pour la « projeter » à la volée.

Accès concurrent aux données

Pour l’accès concurrent aux tables, nous utilisons le multiversionnement. Autrement dit, lorsqu’une table est lue et mise à jour simultanément, les données sont lues à partir d’un ensemble de parts tel qu’il existe au moment de la requête. Il n’y a pas de verrous de longue durée. Les insertions ne gênent pas les opérations de lecture. La lecture d’une table est automatiquement parallélisée.

TTL pour les colonnes et les tables

Détermine la durée de vie des valeurs. La clause TTL peut être définie pour l’ensemble de la table ainsi que pour chaque colonne individuellement. Un TTL au niveau de la table peut également spécifier la logique de déplacement automatique des données entre les disques et les volumes, ou de recompression des parts dont toutes les données ont expiré. Les expressions doivent s’évaluer en type de données Date, Date32, DateTime ou DateTime64.
Évitez les fonctions non déterministes dans les expressions TTLTTL est évalué lors des merges en arrière-plan, et non au moment de l’insertion. Les fonctions comme rand(), now() ou now64() sont réévaluées à chaque merge, ce qui entraîne un comportement de suppression imprévisible. ClickHouse bloque les expressions sans aucune dépendance à une colonne, mais ne rejette pas actuellement les fonctions non déterministes combinées à une référence de colonne (par ex. ts + rand()). Les expressions TTL doivent reposer uniquement sur des valeurs déterministes dérivées des colonnes afin d’obtenir des résultats prévisibles.
Syntaxe Définition de la durée de vie d’une colonne :
Pour définir interval, utilisez les opérateurs d’intervalle de temps, par exemple :

TTL de colonne

Lorsque les valeurs de la colonne expirent, ClickHouse les remplace par les valeurs par défaut du type de données de la colonne. Si toutes les valeurs de la colonne d’une part de données expirent, ClickHouse supprime cette colonne de la part de données dans le système de fichiers. La clause TTL ne peut pas être utilisée pour les colonnes de clé. Exemples

Création d’une table avec TTL :

Ajout d’un TTL à une colonne d’une table existante

Modification du TTL d’une colonne

TTL de table

Une table peut comporter une expression de suppression des lignes expirées, ainsi que plusieurs expressions de déplacement automatique des parts entre disques ou volumes. Lorsque des lignes de la table expirent, ClickHouse supprime toutes les lignes correspondantes. Pour le déplacement ou la recompression des parts, toutes les lignes d’une part doivent satisfaire aux critères de l’expression TTL.
Un type de règle TTL peut être spécifié après chaque expression TTL. Il détermine l’action à effectuer une fois que l’expression est satisfaite (qu’elle atteint l’heure actuelle) :
  • DELETE - supprime les lignes expirées (action par défaut) ;
  • RECOMPRESS codec_name - recompresse la part de données avec codec_name ;
  • TO DISK 'aaa' - déplace la part vers le disque aaa ;
  • TO VOLUME 'bbb' - déplace la part vers le disque bbb ;
  • GROUP BY - agrège les lignes expirées.
L’action DELETE peut être utilisée avec la clause WHERE pour supprimer uniquement certaines lignes expirées en fonction d’une condition de filtrage :
L’expression GROUP BY doit être un préfixe de la clé primaire de la table. Si une colonne ne fait pas partie de l’expression GROUP BY et n’est pas définie explicitement dans la clause SET, alors, dans la ligne de résultat, elle contient une valeur quelconque issue des lignes regroupées (comme si la fonction d’agrégation any lui était appliquée). Exemples

Création d’une table avec TTL :

Modification du TTL de la table :

Création d’une table dont les lignes expirent au bout d’un mois. Les lignes expirées dont la date tombe un lundi sont supprimées :

Création d’une table avec recompression des lignes expirées :

Création d’une table dans laquelle les lignes expirées sont agrégées. Dans les lignes de résultat, x contient la valeur maximale des lignes regroupées, y la valeur minimale, et d une valeur quelconque prise parmi les lignes regroupées.

Suppression des données expirées

Les données dont le TTL a expiré sont supprimées lorsque ClickHouse fusionne des parts de données. Lorsque ClickHouse détecte que des données ont expiré, il effectue une fusion non planifiée. Pour contrôler la fréquence de ces fusions, vous pouvez définir merge_with_ttl_timeout. Si cette valeur est trop faible, de nombreuses fusions non planifiées pourront être effectuées, ce qui risque de consommer beaucoup de ressources. Si vous exécutez la requête SELECT entre deux fusions, il se peut que vous obteniez des données expirées. Pour l’éviter, utilisez la requête OPTIMIZE avant SELECT. Voir aussi

Types de disque

En plus des périphériques de bloc locaux, ClickHouse prend en charge les types de stockage suivants :

Utiliser plusieurs périphériques bloc pour le stockage des données

Introduction

Les moteurs de table de la famille MergeTree peuvent stocker les données sur plusieurs périphériques de stockage par blocs. Cela peut par exemple être utile lorsque les données d’une table donnée se répartissent implicitement entre données « chaudes » et « froides ». Les données les plus récentes sont régulièrement consultées, mais ne nécessitent qu’un faible espace de stockage. À l’inverse, le volume important de données historiques est rarement sollicité. Si plusieurs disques sont disponibles, les données « chaudes » peuvent être placées sur des disques rapides (par exemple, des SSD NVMe ou en mémoire), tandis que les données « froides » peuvent être stockées sur des supports relativement lents (par exemple, des HDD). Cela s’applique à tous les types de disques, y compris S3 et les autres disques de stockage objet. Par exemple, vous pouvez répartir les données entre plusieurs buckets S3 au sein d’un même volume, ou créer des politiques hiérarchisées qui déplacent les données des disques locaux vers S3. Voir Using S3 disks with multiple volumes pour plus de détails. Une part de données est la plus petite unité déplaçable pour les moteurs de table MergeTree. Les données appartenant à une même part sont stockées sur un seul disque. Les parts de données peuvent être déplacées entre les disques en arrière-plan (selon les paramètres utilisateur), ainsi qu’au moyen des requêtes ALTER.

Termes

  • Disque — Périphérique de bloc monté sur le système de fichiers.
  • Disque par défaut — Disque qui stocke le chemin spécifié dans le paramètre du serveur path.
  • Volume — Ensemble ordonné de disques équivalents (semblable à JBOD).
  • Politique de stockage — Ensemble de volumes et règles de déplacement des données entre eux.
Les noms attribués aux entités décrites figurent dans les tables système system.storage_policies et system.disks. Pour appliquer à une table l’une des politiques de stockage configurées, utilisez le paramètre storage_policy des tables de la famille de moteurs MergeTree.

Configuration

Les disques, les volumes et les politiques de stockage doivent être déclarés dans la balise <storage_configuration>, par exemple dans un fichier du répertoire config.d.
Les disques peuvent également être déclarés dans la section SETTINGS d’une requête. Cela est utile pour une analyse ponctuelle afin d’attacher temporairement un disque hébergé, par exemple, à une URL. Consultez stockage dynamique pour plus de détails.
Structure de la configuration :
Balises :
  • <disk_name_N> — Nom du disque. Les noms doivent être différents pour tous les disques.
  • path — chemin sous lequel le serveur stockera les données (dossiers data et shadow), doit se terminer par ’/’.
  • keep_free_space_bytes — quantité d’espace disque libre à réserver.
L’ordre de définition des disques n’a pas d’importance. Balisage de configuration des politiques de stockage :
Tags :
  • policy_name_N — Nom de la politique. Les noms de politique doivent être uniques.
  • volume_name_N — Nom du volume. Les noms de volume doivent être uniques.
  • disk — un disque au sein d’un volume.
  • max_data_part_size_bytes — la taille maximale d’une part pouvant être stockée sur l’un des disques du volume. Si la taille estimée d’une part fusionnée dépasse max_data_part_size_bytes, cette part sera écrite sur le volume suivant. En pratique, cette fonctionnalité permet de conserver les parts nouvelles ou de petite taille sur un volume rapide (SSD) et de les déplacer vers un volume lent (HDD) lorsqu’elles deviennent volumineuses. N’utilisez pas ce paramètre si votre politique ne comporte qu’un seul volume.
  • move_factor — lorsque l’espace disponible devient inférieur à ce facteur, les données commencent automatiquement à être déplacées vers le volume suivant, s’il existe (par défaut, 0.1). ClickHouse trie les parts existantes par taille, de la plus grande à la plus petite (ordre décroissant), et sélectionne les parts dont la taille totale est suffisante pour satisfaire la condition move_factor. Si la taille totale de toutes les parts est insuffisante, toutes les parts seront déplacées.
  • perform_ttl_move_on_insert — Désactive le TTL move lors de l’INSERT d’une part de données. Par défaut (si cette option est activée), si vous insérez une part de données déjà expirée selon la règle de TTL move, elle est immédiatement placée sur un volume/disque déclaré dans la règle de déplacement. Cela peut considérablement ralentir l’insert si le volume/disque de destination est lent (par ex. S3). Si cette option est désactivée, la part de données déjà expirée est écrite sur le volume par défaut, puis déplacée juste après vers le volume TTL.
  • load_balancing - Politique d’équilibrage des disques, round_robin ou least_used.
  • least_used_ttl_ms - Configure le timeout (en millisecondes) de mise à jour de l’espace disponible sur tous les disques (0 - mise à jour systématique, -1 - ne jamais mettre à jour, la valeur par défaut est 60000). Notez que, si le disque ne peut être utilisé que par ClickHouse et n’est pas sujet à un redimensionnement/réduction à chaud du système de fichiers, vous pouvez utiliser -1 ; dans tous les autres cas, cela n’est pas recommandé, car cela finira par entraîner une répartition incorrecte de l’espace.
  • prefer_not_to_merge — Vous ne devriez pas utiliser ce paramètre. Il désactive la fusion des parts de données sur ce volume (ce qui est nuisible et entraîne une dégradation des performances). Lorsque ce paramètre est activé (ne le faites pas), la fusion des données sur ce volume n’est pas autorisée (ce qui est mauvais). Cela permet (mais vous n’en avez pas besoin) de contrôler (si vous voulez contrôler quelque chose, vous faites une erreur) la manière dont ClickHouse fonctionne avec des disques lents (mais ClickHouse sait mieux faire, donc n’utilisez pas ce paramètre).
  • volume_priority — Définit la priorité (ordre) selon laquelle les volumes sont remplis. Une valeur plus faible signifie une priorité plus élevée. Les valeurs du paramètre doivent être des nombres naturels et couvrir collectivement l’intervalle de 1 à N (la priorité la plus faible étant attribuée à N), sans en sauter aucune.
    • Si tous les volumes sont marqués, ils sont priorisés dans l’ordre indiqué.
    • Si seulement certains volumes sont marqués, ceux qui ne le sont pas ont la priorité la plus faible et sont priorisés dans l’ordre où ils sont définis dans la config.
    • Si aucun volume n’est marqué, leur priorité est définie en fonction de l’ordre dans lequel ils sont déclarés dans la configuration.
    • Deux volumes ne peuvent pas avoir la même valeur de priorité.
Exemples de configuration :
Dans l’exemple donné, la policy hdd_in_order implémente l’approche round-robin. Ainsi, cette policy ne définit qu’un seul volume (single) ; les parties de données sont stockées sur tous ses disques selon un ordre circulaire. Une telle policy peut être très utile si plusieurs disques similaires sont montés sur le système, mais que RAID n’est pas configuré. Gardez à l’esprit que chaque disque pris individuellement n’est pas fiable et que vous pouvez compenser cela avec un facteur de réplication de 3 ou plus. S’il existe différents types de disques sur le système, la policy moving_from_ssd_to_hdd peut être utilisée à la place. Le volume hot se compose d’un disque SSD (fast_ssd), et la taille maximale d’une part pouvant être stockée sur ce volume est de 1GB. Toutes les parts dont la taille est supérieure à 1GB seront stockées directement sur le volume cold, qui contient un disque HDD disk1. De plus, une fois que le disque fast_ssd est rempli à plus de 80 %, les données seront transférées vers disk1 par un processus d’arrière-plan. L’ordre d’énumération des volumes au sein d’une politique de stockage est important si au moins l’un des volumes listés n’a pas de paramètre volume_priority explicite. Une fois qu’un volume est trop rempli, les données sont déplacées vers le suivant. L’ordre d’énumération des disques est également important, car les données y sont stockées à tour de rôle. Lors de la création d’une table, il est possible de lui appliquer l’une des stratégies de stockage configurées :
La politique de stockage default signifie qu’un seul volume est utilisé, lequel se compose d’un seul disque indiqué dans <path>. Vous pouvez modifier la politique de stockage après la création de la table avec la requête [ALTER TABLE … MODIFY SETTING] ; la nouvelle politique doit inclure tous les anciens disques et volumes en conservant les mêmes noms. Le nombre de threads qui effectuent les déplacements en arrière-plan des parties de données peut être modifié via le paramètre background_move_pool_size.

Détails

Dans le cas des tables MergeTree, les données sont écrites sur le disque de différentes manières :
  • À la suite d’une insertion (requête INSERT).
  • Pendant les fusions en arrière-plan et les mutations.
  • Lors d’un téléchargement depuis une autre réplique.
  • À la suite du gel d’une partition ALTER TABLE … FREEZE PARTITION.
Dans tous ces cas, à l’exception des mutations et du gel de partition, une part est stockée sur un volume et un disque conformément à la politique de stockage définie :
  1. Le premier volume (dans l’ordre de définition) qui dispose de suffisamment d’espace disque pour stocker une part (unreserved_space > current_part_size) et autorise le stockage de parts d’une taille donnée (max_data_part_size_bytes > current_part_size) est choisi.
  2. Au sein de ce volume, on choisit le disque qui suit celui utilisé pour stocker le fragment de données précédent et qui dispose d’un espace libre supérieur à la taille de la part (unreserved_space - keep_free_space_bytes > current_part_size).
En interne, les mutations et le gel de partition utilisent des liens physiques. Les liens physiques entre différents disques ne sont pas pris en charge ; par conséquent, dans ces cas, les parts résultantes sont stockées sur les mêmes disques que les parts initiales. En arrière-plan, les parts sont déplacées entre les volumes en fonction de la quantité d’espace libre (paramètre move_factor), selon l’ordre dans lequel les volumes sont déclarés dans le fichier de configuration. Les données ne sont jamais transférées depuis le dernier volume vers le premier. Il est possible d’utiliser les tables système system.part_log (champ type = MOVE_PART) et system.parts (champs path et disk) pour surveiller les déplacements en arrière-plan. Des informations détaillées sont également disponibles dans les logs du serveur. L’utilisateur peut forcer le déplacement d’une part ou d’une partition d’un volume vers un autre à l’aide de la requête ALTER TABLE … MOVE PART|PARTITION … TO VOLUME|DISK …, toutes les restrictions applicables aux opérations en arrière-plan étant prises en compte. La requête lance elle-même le déplacement et n’attend pas la fin des opérations en arrière-plan. L’utilisateur recevra un message d’erreur si l’espace libre disponible n’est pas suffisant ou si l’une des conditions requises n’est pas remplie. Le déplacement des données n’interfère pas avec la réplication des données. Par conséquent, différentes politiques de stockage peuvent être spécifiées pour la même table sur différentes répliques. Une fois les fusions et mutations en arrière-plan terminées, les anciennes parts ne sont supprimées qu’après un certain délai (old_parts_lifetime). Pendant cette période, elles ne sont pas déplacées vers d’autres volumes ou disques. Par conséquent, jusqu’à leur suppression définitive, elles sont toujours prises en compte dans l’évaluation de l’espace disque occupé. L’utilisateur peut répartir de nouvelles parts volumineuses entre différents disques d’un volume JBOD de manière équilibrée à l’aide du paramètre min_bytes_to_rebalance_partition_over_jbod.

Utilisation du stockage externe pour les données

Les moteurs de table de la famille MergeTree peuvent stocker des données dans S3, AzureBlobStorage et HDFS à l’aide d’un disque de type s3, azure_blob_storage ou hdfs, respectivement. Consultez la configuration des options de stockage externe pour plus de détails. Exemple d’utilisation de S3 comme stockage externe à l’aide d’un disque de type s3. Extrait de configuration :
Voir aussi la configuration des options de stockage externe.

Utiliser des disques S3 avec plusieurs volumes

Les disques S3 (et les autres disques de stockage d’objets) peuvent être utilisés dans des politiques de stockage à plusieurs disques et à plusieurs volumes de la même manière que les disques locaux. Cela permet de répartir les données sur plusieurs buckets S3 au sein d’un même volume (de type JBOD), ou de mettre en place des politiques de stockage hiérarchisé avec des volumes S3. Par exemple, pour répartir les données entre deux buckets S3 en round-robin :
Vous pouvez également combiner des volumes locaux et S3 dans une politique hiérarchisée, par exemple en déplaçant les données d’un SSD local vers S3 au fil du temps :
Lorsque use_environment_credentials est utilisé pour l’authentication S3, les identifiants d’environnement (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN) sont partagés entre tous les disques S3. Il n’est pas possible d’utiliser des identifiants d’environnement différents selon les disques. Si vous avez besoin d’identifiants distincts pour chaque disque S3, utilisez plutôt des paramètres access_key_id et secret_access_key explicites pour chaque disque.
Il est possible de configurer des tables MergeTree non répliquées dans un scénario avec un seul writer et plusieurs lecteurs sur un stockage partagé. Cela est rendu possible par l’actualisation automatique de la liste des parts, qui peut être configurée sur les lecteurs. Notez que cela nécessite des métadonnées de système de fichiers partagées entre les répliques (ou table_disk = true avec un disque local à la table). Voir refresh_parts_interval and table_disk.
configuration du cacheLes versions 22.3 à 22.7 de ClickHouse utilisent une configuration du cache différente ; consultez using local cache si vous utilisez l’une de ces versions.

Colonnes virtuelles

  • _part — Nom d’une part.
  • _part_index — Indice séquentiel de la part dans le résultat de la requête.
  • _part_starting_offset — Ligne de début cumulée de la part dans le résultat de la requête.
  • _part_offset — Numéro de la ligne dans la part.
  • _part_granule_offset — Numéro du granule dans la part.
  • _partition_id — Nom d’une partition.
  • _part_uuid — Identifiant unique de la part (si le paramètre MergeTree assign_part_uuids est activé).
  • _part_data_version — Version des données de la part (soit le numéro de bloc minimal, soit la version de la mutation).
  • _partition_value — Valeurs (un tuple) d’une expression partition by.
  • _sample_factor — Facteur d’échantillonnage (issu de la requête).
  • _block_number — Numéro d’origine du bloc pour la ligne, attribué lors de l’insertion et conservé lors des fusions lorsque le paramètre enable_block_number_column est activé.
  • _block_offset — Numéro d’origine de la ligne dans le bloc, attribué lors de l’insertion et conservé lors des fusions lorsque le paramètre enable_block_offset_column est activé.
  • _disk_name — Nom du disque utilisé pour le stockage.

Statistiques de colonne

La déclaration des statistiques figure dans la section des colonnes de la requête CREATE des tables de la famille *MergeTree* :
Nous pouvons également manipuler les statistiques à l’aide d’instructions ALTER :
Ces statistiques légères agrègent des informations sur la répartition des valeurs dans les colonnes. Elles sont stockées dans chaque part et mises à jour à chaque insertion. Elles ne peuvent être utilisées pour l’optimisation PREWHERE que si l’on active set use_statistics = 1.

Élagage des parts avec des statistiques

Lorsque use_statistics_for_part_pruning est activé, les statistiques peuvent être utilisées pour l’élagage des parts. Actuellement, seules les statistiques basic (ainsi que les statistiques minmax obsolètes) prennent en charge l’élagage des parts. Lorsque de telles statistiques sont définies sur une colonne, ClickHouse enregistre les valeurs minimale et maximale de cette colonne dans chaque part. L’élagage des parts permet d’éviter la lecture de parts de données entières lorsque la condition de filtre de la requête ne peut correspondre à aucune ligne dans cette part. Exemple :

Types disponibles de statistiques de colonne

  • basic Un ensemble compact de résumés à valeur unique dérivés d’une colonne. Selon le type de la colonne, les éléments suivants sont renseignés :
    • pour toute colonne dont les valeurs sont représentées par un nombre (entiers, flottants, Decimal*, Date*, DateTime*, Enum*, IPv4, …) : les valeurs minimale et maximale, qui permettent d’estimer la sélectivité des filtres de plage et d’effectuer l’élagage des parts ;
    • pour les colonnes String et FixedString : la longueur totale en octets des valeurs non NULL (à partir de laquelle la longueur moyenne des chaînes peut être déduite) ;
    • pour les colonnes Nullable et LowCardinality(Nullable) : le nombre de valeurs NULL, que l’optimiseur utilise pour exclure les lignes NULL des estimations de sélectivité. Une seule statistique basic peut renseigner plusieurs de ces éléments à la fois — par exemple, sur une colonne Nullable(UInt32), elle suit à la fois les min/max numériques et le nombre de valeurs nulles. Par rapport à minmax, basic fonctionne aussi sur les colonnes String / FixedString et peut être déclarée sur des wrappers Nullable de types comme UUID ou IPv6 uniquement pour suivre le nombre de valeurs nulles.
  • minmax (obsolète)
Les statistiques minmax sont obsolètes et ne peuvent plus être créées (CREATE TABLE ... STATISTICS(minmax) et ALTER TABLE ... ADD/MODIFY STATISTICS ... TYPE minmax renvoient une erreur). Les tables et parts existantes avec des statistiques minmax continuent de fonctionner. Utilisez plutôt les statistiques basic.
  • tdigest
Les statistiques de type tdigest ont un coût de création élevé et peuvent ralentir l’ingestion des données.
Des sketches TDigest qui permettent de calculer des percentiles approximatifs (par ex. le 90e percentile) pour les colonnes numériques.
  • uniq Des sketches BJKST qui fournissent une estimation du nombre de valeurs distinctes contenues dans une colonne. Utilise en interne uniq.
  • uniq_v2 Similaire à uniq, mais utilise en interne uniqCombined(12) (une variante de HyperLogLog). Consomme moins de mémoire que uniq et peut être compilé plus rapidement.
  • countmin
Les statistiques de type countmin ont un coût de création élevé et peuvent ralentir l’ingestion des données.
Des sketches CountMin qui fournissent un décompte approximatif de la fréquence de chaque valeur dans une colonne.

Types de données pris en charge

Tous les éléments ci-dessus acceptent également les wrappers Nullable et LowCardinality(Nullable) des types indiqués. Basic peut aussi être déclaré sur des wrappers Nullable de types comme UUID ou IPv6, uniquement pour suivre le nombre de valeurs nulles.

Opérations prises en charge

Pour basic sur les colonnes String / FixedString, la statistique n’enregistre que la longueur totale en octets des valeurs non-NULL (utilisée pour estimer la longueur moyenne des chaînes) et le nombre de valeurs NULL ; les filtres par plage et l’élagage des parts ne s’appuient pas sur elle.

Paramètres au niveau des colonnes

Certains paramètres de MergeTree peuvent être redéfinis au niveau des colonnes :
  • max_compress_block_size — Taille maximale des blocs de données non compressées avant leur compression pour l’écriture dans une table.
  • min_compress_block_size — Taille minimale des blocs de données non compressées requise pour la compression lors de l’écriture du mark suivant.
Exemple :
Les paramètres au niveau des colonnes peuvent être modifiés ou supprimés à l’aide de ALTER MODIFY COLUMN, par exemple :
  • Supprimez SETTINGS de la déclaration de la colonne :
  • Modifiez un paramètre :
  • Réinitialise un ou plusieurs paramètres et supprime également la déclaration du paramètre dans l’expression de colonne de la requête CREATE de la table.
Dernière modification le 24 juillet 2026