Tous les produits
Search
Centre de documentation

ApsaraDB for SelectDB:Modèles de données

Dernière mise à jour :Aug 11, 2026

ApsaraDB for SelectDB prend en charge trois modèles de données. Choisissez le modèle approprié avant de créer une table, car ce choix est définitif.

Modèle Cas d'usage idéal Limitation principale
Modèle de clé d'agrégation Requêtes de rapports à schéma fixe, métriques pré-agrégées COUNT(*) est coûteux ; chaque colonne de valeur est liée à un seul type d'agrégation
Modèle de clé unique Données relationnelles nécessitant l'unicité de la clé primaire (commandes, profils utilisateur) Pré-agrégation ROLLUP impossible
Modèle de clé dupliquée Requêtes ad hoc, analyse de journaux, stockage de données brutes Aucune pré-agrégation ; aucune déduplication automatique

Contexte

Dans ApsaraDB for SelectDB, les tables comportent des lignes et des colonnes. Ces dernières se divisent en deux catégories :

  • Colonnes de clé : correspondent aux colonnes de dimension. Elles sont définies après les mots-clés DUPLICATE KEY, AGGREGATE KEY ou UNIQUE KEY dans une instruction CREATE TABLE.

  • Colonnes de valeur : correspondent aux colonnes de métrique. Il s'agit de toutes les colonnes non répertoriées comme colonnes de clé.

Ces deux catégories correspondent directement aux trois modèles de données.

Modèle de clé d'agrégation

Le modèle de clé d'agrégation pré-agrège les données lors de l'écriture. Lorsque vous importez des lignes partageant des valeurs identiques dans toutes les colonnes de clé, SelectDB les fusionne en une seule ligne. Chaque colonne de valeur est agrégée selon la fonction spécifiée dans l'instruction CREATE TABLE.

Ce modèle convient aux requêtes de rapports avec des schémas d'agrégation fixes, par exemple pour les utilisateurs actifs quotidiens ou les revenus par région. Si vos requêtes impliquent des logiques d'agrégation variables, ou si vous avez besoin d'un COUNT(*) rapide, privilégiez le modèle de clé dupliquée ou le modèle de clé unique avec MoW. Consultez la section Limitations du modèle de clé d'agrégation pour plus de détails.

Types d'agrégation

Type d'agrégation Description
SUM Calcule la somme sur l'ensemble des lignes. S'applique aux valeurs numériques.
MIN Conserve la valeur minimale. S'applique aux valeurs numériques.
MAX Conserve la valeur maximale. S'applique aux valeurs numériques.
REPLACE Remplace la valeur précédente par la nouvelle valeur importée. Pour les lignes ayant les mêmes colonnes de clé, les valeurs sont remplacées selon l'ordre d'importation.
REPLACE_IF_NOT_NULL Identique à REPLACE, mais ignore les valeurs null. Spécifiez null (et non une chaîne vide) comme valeur par défaut de la colonne ; sinon, les chaînes vides seront écrasées.
HLL_UNION Agrège les colonnes de type HyperLogLog (HLL) à l'aide de l'algorithme HLL.
BITMAP_UNION Agrège les colonnes BITMAP via une agrégation par union.

Exemple 1 : Agrégation de base lors de l'importation

La table example_tbl1 enregistre les données de visite des utilisateurs. Les colonnes de clé (user_id, date, city, age, sex) identifient les enregistrements uniques ; les colonnes de valeur stockent les métriques.

Nom de la colonne Type Type d'agrégation Commentaire
user_id LARGEINT N/A ID de l'utilisateur.
date DATE N/A Date d'écriture des données dans la table.
city VARCHAR(20) N/A Ville de résidence de l'utilisateur.
age SMALLINT N/A Âge de l'utilisateur.
sex TINYINT N/A Genre de l'utilisateur.
last_visit_date DATETIME REPLACE Dernière visite de l'utilisateur.
cost BIGINT SUM Montant dépensé par l'utilisateur.
max_dwell_time INT MAX Temps de présence maximum de l'utilisateur.
min_dwell_time INT MIN Temps de présence minimum de l'utilisateur.
CREATE TABLE IF NOT EXISTS test.example_tbl1
(
    `user_id` LARGEINT NOT NULL COMMENT "The user ID",
    `date` DATE NOT NULL COMMENT "The date on which data is written to the table",
    `city` VARCHAR(20) COMMENT "The city in which the user resides",
    `age` SMALLINT COMMENT "The age of the user",
    `sex` TINYINT COMMENT "The gender of the user",
    `last_visit_date` DATETIME REPLACE DEFAULT "1970-01-01 00:00:00" COMMENT "The last time when the user paid a visit",
    `cost` BIGINT SUM DEFAULT "0" COMMENT "The amount of money that the user spends",
    `max_dwell_time` INT MAX DEFAULT "0" COMMENT "The maximum dwell time of the user",
    `min_dwell_time` INT MIN DEFAULT "99999" COMMENT "The minimum dwell time of the user"
)
AGGREGATE KEY(`user_id`, `date`, `city`, `age`, `sex`)
DISTRIBUTED BY HASH(`user_id`) BUCKETS 16;

Insérez les lignes suivantes :

user_id date city age sex last_visit_date cost max_dwell_time min_dwell_time
10000 2017-10-01 Beijing 20 0 2017-10-01 06:00:00 20 10 10
10000 2017-10-01 Beijing 20 0 2017-10-01 07:00:00 15 2 2
10001 2017-10-01 Beijing 30 1 2017-10-01 17:05:45 2 22 22
10002 2017-10-02 Shanghai 20 1 2017-10-02 12:59:12 200 5 5
10003 2017-10-02 Guangzhou 32 0 2017-10-02 11:20:00 30 11 11
10004 2017-10-01 Shenzhen 35 0 2017-10-01 10:00:15 100 3 3
10004 2017-10-03 Shenzhen 35 0 2017-10-03 10:20:22 11 6 6
INSERT INTO example_db.example_tbl_agg1 VALUES
(10000,"2017-10-01","Beijing",20,0,"2017-10-01 06:00:00",20,10,10),
(10000,"2017-10-01","Beijing",20,0,"2017-10-01 07:00:00",15,2,2),
(10001,"2017-10-01","Beijing",30,1,"2017-10-01 17:05:45",2,22,22),
(10002,"2017-10-02","Shanghai",20,1,"2017-10-02 12:59:12",200,5,5),
(10003,"2017-10-02","Guangzhou",32,0,"2017-10-02 11:20:00",30,11,11),
(10004,"2017-10-01","Shenzhen",35,0,"2017-10-01 10:00:15",100,3,3),
(10004,"2017-10-03","Shenzhen",35,0,"2017-10-03 10:20:22",11,6,6);

Après l'importation, SelectDB stocke une seule ligne agrégée pour l'utilisateur 10000 (les lignes 1 et 2 partagent les mêmes colonnes de clé). Les autres utilisateurs ayant des clés uniques, leurs lignes restent inchangées :

user_id date city age sex last_visit_date cost max_dwell_time min_dwell_time
10000 2017-10-01 Beijing 20 0 2017-10-01 07:00:00 35 10 2
10001 2017-10-01 Beijing 30 1 2017-10-01 17:05:45 2 22 22
10002 2017-10-02 Shanghai 20 1 2017-10-02 12:59:12 200 5 5
10003 2017-10-02 Guangzhou 32 0 2017-10-02 11:20:00 30 11 11
10004 2017-10-01 Shenzhen 35 0 2017-10-01 10:00:15 100 3 3
10004 2017-10-03 Shenzhen 35 0 2017-10-03 10:20:22 11 6 6

Agrégation de la ligne de l'utilisateur 10000 :

  • last_visit_date (REPLACE) : 2017-10-01 06:00:00 est remplacé par 2017-10-01 07:00:00.

    Lorsque le type REPLACE s'applique au sein d'un même lot d'importation, l'ordre de remplacement n'est pas garanti. La valeur stockée peut correspondre à l'un ou l'autre horodatage. Entre différents lots, le lot le plus récent l'emporte toujours.
  • cost (SUM) : 20 + 15 = 35.

  • max_dwell_time (MAX) : max(10, 2) = 10.

  • min_dwell_time (MIN) : min(10, 2) = 2.

Une fois l'agrégation terminée, les lignes brutes d'origine disparaissent du stockage.

Exemple 2 : Agrégation de nouvelles données avec des données existantes

Cet exemple illustre l'agrégation par SelectDB d'un second lot d'importation avec des données déjà stockées.

Créez example_tbl2 (même schéma que example_tbl1) :

CREATE TABLE IF NOT EXISTS test.example_tbl2
(
    `user_id` LARGEINT NOT NULL COMMENT "The user ID",
    `date` DATE NOT NULL COMMENT "The date on which data is written to the table",
    `city` VARCHAR(20) COMMENT "The city in which the user resides",
    `age` SMALLINT COMMENT "The age of the user",
    `sex` TINYINT COMMENT "The gender of the user",
    `last_visit_date` DATETIME REPLACE DEFAULT "1970-01-01 00:00:00" COMMENT "The last time when the user paid a visit",
    `cost` BIGINT SUM DEFAULT "0" COMMENT "The amount of money that the user spends",
    `max_dwell_time` INT MAX DEFAULT "0" COMMENT "The maximum dwell time of the user",
    `min_dwell_time` INT MIN DEFAULT "99999" COMMENT "The minimum dwell time of the user"
)
AGGREGATE KEY(`user_id`, `date`, `city`, `age`, `sex`)
DISTRIBUTED BY HASH(`user_id`) BUCKETS 16;

Lot d'importation 1 :

INSERT INTO test.example_tbl2 VALUES
(10000,"2017-10-01","Beijing",20,0,"2017-10-01 06:00:00",20,10,10),
(10000,"2017-10-01","Beijing",20,0,"2017-10-01 07:00:00",15,2,2),
(10001,"2017-10-01","Beijing",30,1,"2017-10-01 17:05:45",2,22,22),
(10002,"2017-10-02","Shanghai",20,1,"2017-10-02 12:59:12",200,5,5),
(10003,"2017-10-02","Guangzhou",32,0,"2017-10-02 11:20:00",30,11,11),
(10004,"2017-10-01","Shenzhen",35,0,"2017-10-01 10:00:15",100,3,3),
(10004,"2017-10-03","Shenzhen",35,0,"2017-10-03 10:20:22",11,6,6);

Lot d'importation 2 (ajoute de nouvelles données pour l'utilisateur 10004 et introduit l'utilisateur 10005) :

INSERT INTO test.example_tbl2 VALUES
(10004,"2017-10-03","Shenzhen",35,0,"2017-10-03 11:22:00",44,19,19),
(10005,"2017-10-03","Changsha",29,1,"2017-10-03 18:11:02",3,1,1);

État final stocké :

user_id date city age sex last_visit_date cost max_dwell_time min_dwell_time
10000 2017-10-01 Beijing 20 0 2017-10-01 07:00:00 35 10 2
10001 2017-10-01 Beijing 30 1 2017-10-01 17:05:45 2 22 22
10002 2017-10-02 Shanghai 20 1 2017-10-02 12:59:12 200 5 5
10003 2017-10-02 Guangzhou 32 0 2017-10-02 11:20:00 30 11 11
10004 2017-10-01 Shenzhen 35 0 2017-10-01 10:00:15 100 3 3
10004 2017-10-03 Shenzhen 35 0 2017-10-03 11:22:00 55 19 6
10005 2017-10-03 Changsha 29 1 2017-10-03 18:11:02 3 1 1

La ligne de l'utilisateur 10004 pour le 2017-10-03 est agrégée sur les deux lots (cost : 11 + 44 = 55 ; max_dwell_time : max(6, 19) = 19 ; min_dwell_time : min(6, 19) = 6). L'utilisateur 10005 étant nouveau, sa ligne est insérée telle quelle.

L'agrégation dans ApsaraDB for SelectDB comporte trois étapes :

  1. Étape ETL (extraction, transformation et chargement) : chaque lot d'importation est agrégé en interne avant écriture.

  2. Étape de compactage des données : le cluster de calcul fusionne en arrière-plan les données issues de différents lots d'importation.

  3. Étape de requête : les données non agrégées restantes sont agrégées lors de la requête.

Le degré d'agrégation à tout instant est transparent. Considérez toujours que les données interrogées sont entièrement agrégées.

Exemple 3 : Conservation des données détaillées avec le modèle de clé d'agrégation

L'ajout d'une colonne à haute cardinalité aux colonnes de clé empêche les lignes de partager la même clé. Cela permet de conserver toutes les données brutes tout en utilisant le modèle de clé d'agrégation.

Ajoutez une colonne timestamp (précise à la seconde) à la clé :

CREATE TABLE IF NOT EXISTS test.example_tbl3
(
    `user_id` LARGEINT NOT NULL COMMENT "The user ID",
    `date` DATE NOT NULL COMMENT "The date on which data is written to the table",
    `timestamp` DATETIME NOT NULL COMMENT "The time when data is written to the table, which is accurate to seconds",
    `city` VARCHAR(20) COMMENT "The city in which the user resides",
    `age` SMALLINT COMMENT "The age of the user",
    `sex` TINYINT COMMENT "The gender of the user",
    `last_visit_date` DATETIME REPLACE DEFAULT "1970-01-01 00:00:00" COMMENT "The last time when the user paid a visit",
    `cost` BIGINT SUM DEFAULT "0" COMMENT "The amount of money that the user spends",
    `max_dwell_time` INT MAX DEFAULT "0" COMMENT "The maximum dwell time of the user",
    `min_dwell_time` INT MIN DEFAULT "99999" COMMENT "The minimum dwell time of the user"
)
AGGREGATE KEY(`user_id`, `date`, `timestamp`, `city`, `age`, `sex`)
DISTRIBUTED BY HASH(`user_id`) BUCKETS 16;

Chaque ligne possédant un timestamp unique, aucune paire de lignes ne partage jamais les mêmes colonnes de clé. Par conséquent, aucune agrégation ne se produit et toutes les données brutes sont conservées.

Limitations du modèle de clé d'agrégation

Le modèle de clé d'agrégation présentant toujours des données entièrement agrégées, certaines requêtes peuvent produire des résultats inattendus ou entraîner des coûts élevés.

Surcharge de COUNT(*)

Prenons une table example_tbl8 avec le schéma suivant :

Nom de la colonne Type Type d'agrégation Commentaire
user_id LARGEINT N/A ID de l'utilisateur.
date DATE N/A Date d'écriture des données dans la table.
cost BIGINT SUM Montant dépensé par l'utilisateur.

Importez deux lots :

Lot 1 :

user_id date cost
10001 2017-11-20 50
10002 2017-11-21 39

Lot 2 :

user_id date cost
10001 2017-11-20 1
10001 2017-11-21 5
10003 2017-11-22 22

Les cinq lignes d'origine peuvent encore exister dans le stockage sous-jacent avant le compactage. L'exécution de COUNT(*) :

SELECT COUNT(*) FROM example_tbl8;

Résultat attendu : 4 (quatre combinaisons de clés uniques). Cependant, si SelectDB analyse uniquement la colonne user_id et ignore l'agrégation, il renvoie 3. S'il compte toutes les lignes non compactées, il renvoie 5. Les deux résultats sont incorrects.

Pour obtenir le résultat correct, le moteur de requête doit analyser toutes les colonnes de clé (user_id et date) et les agréger. Cela implique une analyse complète des clés pour chaque appel à COUNT(*).

Solution de contournement : Ajoutez une colonne count avec une valeur fixe de 1 et un type d'agrégation SUM :

Nom de la colonne Type Type d'agrégation Commentaire
user_id BIGINT N/A ID de l'utilisateur.
date DATE N/A Date d'écriture des données dans la table.
cost BIGINT SUM Montant dépensé par l'utilisateur.
count BIGINT SUM Compteur de lignes.

SELECT SUM(count) FROM table; équivaut à SELECT COUNT(*) FROM table; et s'exécute beaucoup plus rapidement. Notez que cette approche ne prend pas en charge la réimportation de lignes avec les mêmes colonnes de clé, car cela gonflerait le compteur.

Vous pouvez également définir le type d'agrégation de la colonne count sur REPLACE avec une valeur fixe de 1. Cela produit le même résultat que COUNT(*) et permet de réimporter des clés dupliquées.

Sémantique des requêtes d'agrégation

Chaque colonne de valeur est liée à un seul type d'agrégation lors de la création de la table. L'exécution d'une fonction d'agrégation différente sur une colonne de valeur peut retourner des résultats sémantiquement incorrects. Concevez donc le schéma en fonction des types d'agrégation requis.

Modèle de clé unique

Contrairement au modèle de clé d'agrégation, le modèle de clé unique impose l'unicité de la clé primaire au lieu d'agréger les valeurs. Lorsque de nouvelles lignes arrivent avec les mêmes colonnes de clé que des lignes existantes, seule la dernière ligne importée est conservée.

Privilégiez ce modèle pour les données relationnelles avec des exigences d'unicité, telles que les commandes ou les profils utilisateur. Il ne prend pas en charge la pré-agrégation ROLLUP.

ApsaraDB for SelectDB propose deux méthodes d'implémentation :

  • Merge on Write (MoW) : supprime les doublons pendant l'étape d'importation. Recommandé pour des performances de requête optimales.

  • Merge on Read (MoR) : applique la déduplication lors de la requête.

MoW (recommandé)

MoW marque les lignes écrasées comme supprimées lors de l'importation et écrit directement les données les plus récentes. Lors de la requête, les lignes supprimées sont filtrées sans aucune opération de fusion. Cela élimine la surcharge d'agrégation de MoR et permet le pushdown de prédicats dans la plupart des scénarios, ce qui accélère les requêtes d'agrégation.

MoW est désactivé par défaut dans ApsaraDB for SelectDB V3.0. Activez-le en définissant "enable_unique_key_merge_on_write" = "true" lors de la création de la table.
CREATE TABLE IF NOT EXISTS test.example_tbl6
(
    `user_id` LARGEINT NOT NULL COMMENT "The user ID",
    `username` VARCHAR(50) NOT NULL COMMENT "The nickname of the user",
    `city` VARCHAR(20) COMMENT "The city in which the user resides",
    `age` SMALLINT COMMENT "The age of the user",
    `sex` TINYINT COMMENT "The gender of the user",
    `phone` LARGEINT COMMENT "The phone number of the user",
    `address` VARCHAR(500) COMMENT "The address of the user",
    `register_time` DATETIME COMMENT "The time when the user is registered"
)
UNIQUE KEY(`user_id`, `username`)
DISTRIBUTED BY HASH(`user_id`) BUCKETS 16
PROPERTIES (
    "enable_unique_key_merge_on_write" = "true"
);
MoR ne peut pas être mis à niveau de manière transparente vers MoW, car ils organisent les données différemment. Pour migrer, utilisez INSERT INTO unique-mow-table SELECT * FROM source_table afin d'importer les données existantes dans une nouvelle table MoW.
Le signe de suppression unique et la colonne de séquence fonctionnent toujours lorsque MoW est activé.

MoR

MoR applique la logique de déduplication lors de la requête en fusionnant les données à la lecture. Cela équivaut au modèle de clé d'agrégation avec toutes les colonnes de valeur définies sur REPLACE.

CREATE TABLE IF NOT EXISTS test.example_tbl4
(
    `user_id` LARGEINT NOT NULL COMMENT "The user ID",
    `username` VARCHAR(50) NOT NULL COMMENT "The nickname of the user",
    `city` VARCHAR(20) COMMENT "The city in which the user resides",
    `age` SMALLINT COMMENT "The age of the user",
    `sex` TINYINT COMMENT "The gender of the user",
    `phone` LARGEINT COMMENT "The phone number of the user",
    `address` VARCHAR(500) COMMENT "The address of the user",
    `register_time` DATETIME COMMENT "The time when the user is registered"
)
UNIQUE KEY(`user_id`, `username`)
DISTRIBUTED BY HASH(`user_id`) BUCKETS 16;

Le modèle de clé unique MoR ci-dessus est intérieurement identique au modèle de clé d'agrégation suivant, où toutes les colonnes de valeur utilisent REPLACE :

CREATE TABLE IF NOT EXISTS test.example_tbl5
(
    `user_id` LARGEINT NOT NULL COMMENT "The user ID",
    `username` VARCHAR(50) NOT NULL COMMENT "The nickname of the user",
    `city` VARCHAR(20) REPLACE COMMENT "The city in which the user resides",
    `age` SMALLINT REPLACE COMMENT "The age of the user",
    `sex` TINYINT REPLACE COMMENT "The gender of the user",
    `phone` LARGEINT REPLACE COMMENT "The phone number of the user",
    `address` VARCHAR(500) REPLACE COMMENT "The address of the user",
    `register_time` DATETIME REPLACE COMMENT "The time when the user is registered"
)
AGGREGATE KEY(`user_id`, `username`)
DISTRIBUTED BY HASH(`user_id`) BUCKETS 16;

Modèle de clé dupliquée

Le modèle de clé dupliquée se distingue des deux autres car il stocke toutes les lignes exactement telles qu'elles ont été importées, sans agrégation ni contrainte d'unicité. Plusieurs lignes avec les mêmes valeurs de colonnes de clé coexistent sans s'affecter mutuellement.

Utilisez ce modèle pour les requêtes ad hoc sur des données brutes telles que les journaux, lorsque vous avez besoin de tous les détails et que la déduplication ou la pré-agrégation n'est pas nécessaire.

Les colonnes de clé spécifiées dans l'instruction CREATE TABLE servent uniquement de clés de tri, et non d'identifiants uniques. Nous vous recommandons de sélectionner les deux à quatre premières colonnes comme clé dupliquée.

CREATE TABLE IF NOT EXISTS test.example_tbl7
(
    `timestamp` DATETIME NOT NULL COMMENT "The time when the log was generated",
    `type` INT NOT NULL COMMENT "The type of the log",
    `error_code` INT COMMENT "The error code",
    `error_msg` VARCHAR(1024) COMMENT "The error message",
    `op_id` BIGINT COMMENT "The owner ID",
    `op_time` DATETIME COMMENT "The time when the error was handled"
)
DUPLICATE KEY(`timestamp`, `type`, `error_code`)
DISTRIBUTED BY HASH(`type`) BUCKETS 16;
Colonne Type Clé de tri Commentaire
timestamp DATETIME Oui Heure de génération du journal.
type INT Oui Type de journal.
error_code INT Oui Code d'erreur.
error_msg VARCHAR(1024) Non Message d'erreur.
op_id BIGINT Non ID du propriétaire.
op_time DATETIME Non Heure de traitement de l'erreur.

Colonnes de clé selon les modèles

Les colonnes de clé jouent des rôles différents selon le modèle :

Modèle Rôle des colonnes de clé
Modèle de clé dupliquée Clés de tri uniquement — pas d'identifiants uniques
Modèle de clé d'agrégation Clés de tri et identifiants uniques
Modèle de clé unique Clés de tri et identifiants uniques

Choisir un modèle de données

Scénario Modèle recommandé
Rapports d'agrégation à schéma fixe (par exemple, utilisateurs actifs quotidiens, revenus par région) Modèle de clé d'agrégation
Données relationnelles avec contraintes de clé primaire (par exemple, commandes, profils utilisateur) Modèle de clé unique (MoW)
Requêtes d'agrégation hautes performances sur des données à clé primaire Modèle de clé unique avec MoW activé
Analyse de données brutes, requêtes de journaux, exploration ad hoc Modèle de clé dupliquée
Mises à jour partielles de colonnes Modèle de clé unique — voir Mise à jour partielle

Quand éviter le modèle de clé d'agrégation : Ne l'utilisez pas si vos requêtes COUNT(*) doivent être rapides, ou si vous devez exécuter des fonctions d'agrégation différentes des types d'agrégation définis lors de la création de la table. Le modèle de clé d'agrégation n'est efficace que lorsque les lignes se fusionnent de manière significative. Si la plupart des lignes ont des clés uniques, la surcharge de pré-agrégation l'emporte sur les avantages.

Comment MoW améliore les performances de COUNT(*)

MoW utilise un bitmap de suppression pour suivre les lignes écrasées plutôt que d'agréger lors de la requête. En reprenant le scénario à deux lots mentionné dans la limitation du modèle de clé d'agrégation ci-dessus :

Après le lot 1 :

user_id date cost bit de suppression
10001 2017-11-20 50 false
10002 2017-11-21 39 false

Après le lot 2 (la ligne dupliquée du lot 1 est marquée comme supprimée) :

user_id date cost bit de suppression
10001 2017-11-20 50 true
10002 2017-11-21 39 false
user_id date cost bit de suppression
10001 2017-11-20 1 false
10001 2017-11-21 5 false
10003 2017-11-22 22 false

COUNT(*) ignore les lignes avec delete bit = true et n'analyse qu'une seule colonne, retournant ainsi 4 correctement avec une surcharge minimale. Dans l'environnement de test, les requêtes COUNT(*) utilisant la méthode d'implémentation MoW du modèle de clé unique offrent des performances 10 fois supérieures à celles utilisant le modèle de clé d'agrégation.