`CollapsingMergeTree` supprime de manière asynchrone (réduit) les paires de lignes si tous les champs d'une clé de tri (`ORDER BY`) sont équivalents à l'exception du champ particulier `Sign` ce qui peut avoir `1` et `-1` valeur. Les lignes sans paire sont conservées. Pour plus de détails, voir le [Effondrer](#table_engine-collapsingmergetree-collapsing) la section du document.
Lors de la création d'un `CollapsingMergeTree` de table, de la même [les clauses de requête](mergetree.md#table_engine-mergetree-creating-a-table) sont nécessaires, comme lors de la création d'un `MergeTree` table.
Considérez la situation où vous devez enregistrer des données en constante évolution pour un objet. Il semble logique d'avoir une ligne pour un objet et de la mettre à jour à tout changement, mais l'opération de mise à jour est coûteuse et lente pour le SGBD car elle nécessite une réécriture des données dans le stockage. Si vous avez besoin d'écrire des données rapidement, la mise à jour n'est pas acceptable, mais vous pouvez écrire les modifications d'un objet de manière séquentielle comme suit.
Utilisez la colonne particulière `Sign`. Si `Sign = 1` cela signifie que la ligne est un état d'un objet, appelons-la “state” rangée. Si `Sign = -1` il signifie l'annulation de l'état d'un objet avec les mêmes attributs, nous allons l'appeler “cancel” rangée.
Par exemple, nous voulons calculer combien de pages les utilisateurs ont vérifié sur un site et combien de temps ils étaient là. À un certain moment nous écrire la ligne suivante avec l'état de l'activité de l'utilisateur:
Pourquoi nous avons besoin de 2 lignes pour chaque changement lu dans le [Algorithme](#table_engine-collapsingmergetree-collapsing-algorithm) paragraphe.
1. Le programme qui écrit les données doit se souvenir de l'état d'un objet pour pouvoir l'annuler. “Cancel” string doit contenir des copies des champs de clé de tri du “state” chaîne et le contraire `Sign`. Il augmente la taille initiale de stockage, mais permet d'écrire les données rapidement.
2. Les tableaux de plus en plus longs dans les colonnes réduisent l'efficacité du moteur en raison de la charge pour l'écriture. Plus les données sont simples, plus l'efficacité est élevée.
3. Le `SELECT` les résultats dépendent fortement de la cohérence de l'historique des modifications d'objet. Être précis lors de la préparation des données pour l'insertion. Vous pouvez obtenir des résultats imprévisibles dans des données incohérentes, par exemple des valeurs négatives pour des mesures non négatives telles que la profondeur de session.
Lorsque ClickHouse fusionne des parties de données, chaque groupe de lignes consécutives avec la même clé de tri (`ORDER BY`) est réduit à pas plus de deux rangées, une avec `Sign = 1` (“state” ligne) et l'autre avec `Sign = -1` (“cancel” rangée). En d'autres termes, les entrées de l'effondrement.
Aussi quand il y a au moins 2 plus “state” les lignes de “cancel” les lignes, ou au moins 2 de plus “cancel” rangs puis “state” la fusion continue, mais ClickHouse traite cette situation comme une erreur logique et l'enregistre dans le journal du serveur. Cette erreur peut se produire si les mêmes données ont été insérées plus d'une fois.
Le `Sign` est nécessaire car l'algorithme de fusion ne garantit pas que toutes les lignes avec la même clé de tri seront dans la même partie de données résultante et même sur le même serveur physique. Processus de ClickHouse `SELECT` les requêtes avec plusieurs threads, et il ne peut pas prédire l'ordre des lignes dans le résultat. L'agrégation est nécessaire s'il y a un besoin d'obtenir complètement “collapsed” les données de `CollapsingMergeTree` table.
Pour finaliser la réduction, écrivez une requête avec `GROUP BY` fonctions de clause et d'agrégation qui tiennent compte du signe. Par exemple, pour calculer la quantité, l'utilisation `sum(Sign)` plutôt `count()`. Pour calculer la somme de quelque chose, utilisez `sum(Sign * x)` plutôt `sum(x)` et ainsi de suite , et également ajouter `HAVING sum(Sign) > 0`.
Aggregate `count`, `sum` et `avg` pourrait être calculée de cette manière. Aggregate `uniq` peut être calculé si un objet a au moins un état non réduit. Aggregate `min` et `max` impossible de calculer parce que `CollapsingMergeTree` n'enregistre pas l'historique des valeurs des États réduits.
Si vous avez besoin d'extraire des données sans agrégation (par exemple, pour vérifier si des lignes sont présentes dont les valeurs les plus récentes correspondent à certaines conditions), vous pouvez utiliser `FINAL` le modificateur du `FROM` clause. Cette approche est nettement moins efficace.
Nous utilisons deux `INSERT` requêtes pour créer deux parties de données différentes. Si nous insérons les données avec une requête, ClickHouse crée une partie de données et n'effectuera aucune fusion.
Avec deux `INSERT` requêtes, nous avons créé 2 parties de données. Le `SELECT` la requête a été effectuée dans 2 threads, et nous avons obtenu un ordre aléatoire de lignes. L'effondrement n'a pas eu lieu car il n'y avait pas encore de fusion des parties de données. ClickHouse fusionne une partie des données dans un moment inconnu que nous ne pouvons pas prédire.
L'idée est que les fusions ne prennent en compte que les champs clés. Et dans le “Cancel” ligne nous pouvons spécifier des valeurs négatives qui égalisent la version précédente de la ligne lors de la sommation sans utiliser la colonne de signe. Pour cette approche, il est nécessaire de changer le type de données `PageViews`,`Duration` pour stocker les valeurs négatives de UInt8 - \> Int16.