Une conception rigoureuse du schéma de table permet de prendre en charge des fonctionnalités riches et d'améliorer considérablement les performances, la maintenabilité et l'évolutivité du système de base de données. La conception du schéma de la base de données et des tables revêt donc une importance capitale. Cette rubrique décrit les propriétés de table essentielles à prendre en compte lors de la conception d'un schéma de table dans ApsaraDB for SelectDB. Ces informations vous aideront à concevoir vos tables de manière appropriée pour répondre au mieux à vos besoins métier.
Propriétés de table importantes
Lorsque vous stockez vos données métier dans ApsaraDB for SelectDB, il est primordial de définir les propriétés de table clés en fonction de vos exigences métier. Cela vous permet de créer un schéma de table performant et facile à maintenir. Le tableau suivant décrit les propriétés de table importantes d'ApsaraDB for SelectDB.
Propriété de table | Obligatoire | Description | Références |
Modèle de données | Oui | Différents modèles de données correspondent à différents scénarios métier : le modèle Unique prend en charge les contraintes d'unicité sur la clé primaire et répond aux besoins de mise à jour des données flexibles et efficaces. Le modèle Duplicate utilise le mode d'écriture par ajout et convient à l'analyse haute performance des données détaillées. Le modèle Aggregate permet la pré-agrégation des données et s'adapte aux scénarios d'agrégation et de statistiques. | |
Tablet | Oui | Les tablets servent à répartir les données sur différents nœuds d'un cluster afin de gérer et d'interroger de grands volumes de données en tirant parti des capacités d'un système distribué. | |
Partition | Non | Le partitionnement permet de diviser une table brute en plusieurs tables enfants selon des champs spécifiés, tels que l'heure et la région. Cette opération facilite la gestion et l'interrogation des données tout en accélérant les requêtes. | |
Index | Non | Les index permettent de filtrer ou de localiser rapidement les données, ce qui améliore considérablement les performances des requêtes. |
Modèles de données
Sélectionnez un modèle de données adapté aux exigences fonctionnelles et de performance de vos scénarios d'analyse. Chaque modèle correspond à des cas d'usage spécifiques. Cette section présente brièvement les modèles disponibles pour vous aider à choisir celui qui convient le mieux à vos besoins métier. Pour plus d'informations, consultez Modèles de données.
Principes de base
Dans ApsaraDB for SelectDB, les données sont organisées et gérées sous forme de tables au niveau logique. Chaque table se compose de lignes et de colonnes. Une ligne représente une entrée de données dans la table, tandis qu'une colonne décrit un champ spécifique de cette ligne.
Les colonnes se classent dans les catégories suivantes :
Colonne clé : il s'agit des colonnes définies par les mots-clés
UNIQUE KEY,AGGREGATE KEYetDUPLICATE KEYdans l'instruction CREATE TABLE.Colonne de valeur : toutes les autres colonnes entrent dans cette catégorie.
Choisir un modèle
ApsaraDB for SelectDB propose trois types de modèles de données pour les tables : Unique, Duplicate et Aggregate.
Le modèle de données est déterminé lors de la création de la table et ne peut plus être modifié par la suite.
Si aucun modèle n'est spécifié lors de la création, le modèle Duplicate s'applique par défaut et les trois premières colonnes deviennent automatiquement les colonnes clés.
Dans les modèles Unique, Duplicate et Aggregate, les données sont triées selon les colonnes clés.
Modèle de données | Caractéristique | Scénario | Inconvénient |
Unique | La valeur d'une colonne clé est unique pour chaque ligne. Si plusieurs lignes partagent la même valeur pour une colonne clé, la dernière ligne écrite écrase les précédentes. | Ce modèle convient aux scénarios nécessitant des clés primaires uniques ou des mises à jour efficaces, comme l'analyse des commandes e-commerce ou des attributs utilisateurs. |
|
Duplicate | Plusieurs lignes peuvent partager la même valeur pour une colonne clé. Le système conserve simultanément toutes les lignes ayant des valeurs identiques pour une colonne clé. | Offrant une grande efficacité d'écriture et d'interrogation, ce modèle est idéal lorsque toutes les données brutes doivent être conservées, par exemple pour l'analyse détaillée des journaux ou des factures. |
|
Aggregate | La valeur d'une colonne clé est unique pour chaque ligne. Lorsque plusieurs lignes ont la même valeur pour une colonne clé, leurs colonnes de valeur sont pré-agrégées selon le type d'agrégation défini à la création de la table. | Semblable au modèle Cube des entrepôts de données traditionnels, le modèle Aggregate optimise les performances des requêtes grâce à la pré-agrégation. Il est particulièrement adapté aux statistiques agrégées, telles que l'analyse du trafic web ou les rapports personnalisés. |
|
Utiliser un modèle
Utiliser le modèle Unique
Dans le modèle Unique, si plusieurs lignes partagent la même valeur pour une colonne clé, la dernière ligne écrite remplace les précédentes. Ce modèle propose deux méthodes d'implémentation : Merge on Read (MoR) et Merge on Write (MoW).
Mature et stable, la méthode MoW offre d'excellentes performances de requête. Nous recommandons donc son utilisation avec le modèle Unique. L'exemple suivant illustre la mise en œuvre du modèle Unique via la méthode MoW. Pour plus d'informations sur la méthode MoR, reportez-vous à la section MoR de la rubrique « Modèles de données ».
Remarques d'utilisation
Si vous optez pour le modèle Unique avec la méthode MoW, tenez compte des points suivants lors de la création de la table :
Utilisez le mot-clé
UNIQUE KEYpour désigner un champ unique comme clé primaire.-
Activez MoW dans la section PROPERTIES.
"enable_unique_key_merge_on_write" = "true"
Exemple
Le code ci-dessous présente l'instruction SQL permettant de créer la table orders. Dans cet exemple, le modèle Unique est appliqué à la table orders, les champs order_id et order_time forment la clé primaire composite, et la méthode MoW est activée.
CREATE TABLE IF NOT EXISTS orders
(
`order_id` LARGEINT NOT NULL COMMENT "The order ID.",
`order_time` DATETIME NOT NULL COMMENT "The order time.",
`customer_id` LARGEINT NOT NULL COMMENT "The user ID.",
`total_amount` DOUBLE COMMENT "The total amount of the order.",
`status` VARCHAR(20) COMMENT "The order status.",
`payment_method` VARCHAR(20) COMMENT "The payment method.",
`shipping_method` VARCHAR(20) COMMENT "The shipping method.",
`customer_city` VARCHAR(20) COMMENT "The city in which the user resides.",
`customer_address` VARCHAR(500) COMMENT "The address of the user."
)
UNIQUE KEY(`order_id`, `order_time`)
PARTITION BY RANGE(`order_time`) ()
DISTRIBUTED BY HASH(`order_id`)
PROPERTIES (
"enable_unique_key_merge_on_write" = "true",
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.start" = "-7",
"dynamic_partition.end" = "3",
"dynamic_partition.prefix" = "p",
"dynamic_partition.create_history_partition" = "true",
"dynamic_partition.buckets" = "16"
);
Utiliser le modèle Duplicate
Avec le modèle Duplicate, le système conserve simultanément plusieurs lignes partageant la même valeur pour une colonne clé. Ce modèle ne prend pas en charge la pré-agrégation et n'impose pas de clés primaires uniques.
Par exemple, ce modèle permet d'enregistrer et d'analyser les journaux générés par un système métier, en triant les données par heure, type de journal et code d'erreur. Le code suivant montre l'instruction SQL de création de la table log. Ici, le modèle Duplicate est utilisé et les données sont triées selon les champs log_time, log_type et error_code.
CREATE TABLE IF NOT EXISTS log
(
`log_time` DATETIME NOT NULL COMMENT "The time when the log was generated.",
`log_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(`log_time`, `log_type`, `error_code`)
PARTITION BY RANGE(`log_time`) ()
DISTRIBUTED BY HASH(`log_type`)
PROPERTIES (
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.start" = "-7",
"dynamic_partition.end" = "3",
"dynamic_partition.prefix" = "p",
"dynamic_partition.create_history_partition" = "true",
"dynamic_partition.buckets" = "16"
);
Utiliser le modèle Aggregate
Remarques d'utilisation
Dans le modèle Aggregate, lorsque plusieurs lignes partagent la même valeur pour une colonne clé, leurs colonnes de valeur sont pré-agrégées selon le type d'agrégation défini lors de la création de la table. Lors de la création d'une table utilisant ce modèle, respectez les consignes suivantes :
Employez le mot-clé
AGGREGATE KEYpour définir une ou plusieurs colonnes clés. Les lignes ayant des valeurs identiques pour ces colonnes seront agrégées.Définissez un type d'agrégation pour les colonnes de valeur. Le tableau ci-dessous détaille les types disponibles.
Exemple
À titre d'illustration, le modèle Aggregate permet d'effectuer des analyses statistiques sur le comportement des utilisateurs en enregistrant : la dernière visite, la consommation totale, ainsi que les durées de séjour maximale et minimale. Le code suivant présente l'instruction SQL créant la table user_behavior. Dans cet exemple, les colonnes de valeur sont pré-agrégées lorsque les colonnes clés suivantes (user_id, date, city, age et sex) présentent des valeurs identiques sur plusieurs lignes. Les règles d'agrégation appliquées sont les suivantes :
Dernière visite de l'utilisateur : conservation de la valeur maximale du champ last_visit_date.
Consommation totale : calcul de la somme des enregistrements.
Durée de séjour maximale : conservation de la valeur maximale du champ max_dwell_time.
Durée de séjour minimale : conservation de la valeur minimale du champ min_dwell_time.
CREATE TABLE IF NOT EXISTS user_behavior
(
`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`)
PARTITION BY RANGE(`date`) ()
DISTRIBUTED BY HASH(`user_id`)
PROPERTIES (
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.start" = "-7",
"dynamic_partition.end" = "3",
"dynamic_partition.prefix" = "p",
"dynamic_partition.create_history_partition" = "true",
"dynamic_partition.buckets" = "16"
);
Division des données
ApsaraDB for SelectDB organise les données selon deux niveaux de division, comme l'illustre la figure suivante. Au premier niveau, la table est divisée logiquement en partitions, qui constituent la plus petite unité de gestion des données. Au second niveau, chaque partition est physiquement subdivisée en tablets, représentant l'unité minimale pour les opérations telles que la distribution et la migration des données.
Relation entre partitions et tablets
Un tablet appartient à une seule partition, tandis qu'une partition contient plusieurs tablets.
Si le partitionnement est activé lors de la création de la table, celle-ci est d'abord découpée en partitions selon les règles définies, puis en tablets. En l'absence de partitionnement, la table est directement divisée en tablets conformément aux règles de découpage.
Lors de l'écriture, les données sont d'abord dirigées vers une partition, puis réparties entre les différents tablets de cette partition selon les règles de découpage. Cette subdivision supplémentaire des données partitionnées vise à équilibrer la charge et à optimiser l'efficacité des requêtes.
Partitions
Au sein du moteur de stockage d'ApsaraDB for SelectDB, le partitionnement consiste à organiser les données d'une table en plusieurs parties indépendantes selon des règles personnalisées. Cette division logique améliore l'efficacité des requêtes et rend la gestion des données plus flexible. Cette section présente brièvement les partitions pour vous guider dans le choix du mode adapté à vos besoins. Pour plus de détails, consultez la section Partitionnement de la rubrique « Partitionnement et bucketing » ainsi que la rubrique Partitionnement dynamique.
Choisir un mode de partitionnement
ApsaraDB for SelectDB prend en charge deux modes de partitionnement : par plage (range) et par liste (list). Il offre également une fonctionnalité de partitionnement dynamique conviviale pour automatiser la gestion des partitions. Chaque mode répond à des scénarios métier spécifiques.
Mode de partitionnement | Type de données de colonne pris en charge | Méthode de spécification des informations de partition | Scénario |
Range | DATE, DATETIME, TINYINT, SMALLINT, INT, BIGINT et LARGEINT | Quatre méthodes sont disponibles :
| Le partitionnement par plage est idéal pour gérer des intervalles de données, notamment pour un découpage chronologique. |
List | BOOLEAN, TINYINT, SMALLINT, INT, BIGINT, LARGEINT, DATE, DATETIME, CHAR et VARCHAR |
| Le partitionnement par liste convient à la gestion de données basée sur des types existants ou des caractéristiques fixes, où les colonnes clés prennent des valeurs discrètes. Par exemple, il permet de segmenter les données selon la région géographique des utilisateurs. |
Remarques d'utilisation
Dans ApsaraDB for SelectDB, on distingue les tables partitionnées des tables non partitionnées. Le choix d'activer ou non le partitionnement s'effectue lors de la création de la table ; cette propriété est optionnelle mais définitive. Concrètement, vous pouvez ajouter ou supprimer des partitions sur une table partitionnée, mais cette opération est impossible sur une table non partitionnée.
Une ou plusieurs colonnes peuvent servir de clés de partition, à condition qu'il s'agisse de colonnes clés.
Les valeurs des clés de partition doivent toujours être entourées de guillemets doubles ("), quel que soit leur type de données.
En théorie, le nombre de partitions n'est pas limité.
Lors de la création des partitions, veillez à ce que leurs plages ne se chevauchent pas.
Mettre en œuvre le partitionnement
Utiliser le partitionnement par plage
Le partitionnement par plage est la méthode la plus courante pour organiser les données selon des intervalles de champs. Un cas typique consiste à partitionner de grands volumes de séries temporelles par date afin d'en faciliter la gestion et d'optimiser les requêtes.
L'objectif ultime du partitionnement et du découpage en tablets est d'organiser les données de manière rationnelle. Respectez les principes suivants lors de la définition des règles de partitionnement :
Chaque tablet doit contenir entre 1 Go et 10 Go de données.
Adaptez la granularité du partitionnement au volume de données à gérer. Par exemple, si vous devez supprimer quotidiennement des journaux historiques, une granularité journalière est appropriée.
L'exemple de code suivant montre comment créer une table partitionnée permettant de filtrer les données par période et de purger les anciens journaux. Ici, le champ log_time sert de clé de partition.
CREATE TABLE IF NOT EXISTS log
(
`log_time` DATETIME NOT NULL COMMENT "The time when the log was generated.",
`log_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(`log_time`, `log_type`, `error_code`)
PARTITION BY RANGE(`log_time`)
(
PARTITION `p20240201` VALUES [("2024-02-01"), ("2024-02-02")),
PARTITION `p20240202` VALUES [("2024-02-02"), ("2024-02-03")),
PARTITION `p20240203` VALUES [("2024-02-03"), ("2024-02-04"))
)
DISTRIBUTED BY HASH(`log_type`)
PROPERTIES ();
Une fois la table créée, exécutez l'instruction SQL suivante pour afficher ses informations de partitionnement :
SHOW partitions FROM log;
p20240201: [("2024-02-01"), ("2024-02-02"))
p20240202: [("2024-02-02"), ("2024-02-03"))
p20240203: [("2024-02-03"), ("2024-02-04"))
Lors de l'exécution de la requête ci-dessous, seule la partition p20240202: [("2024-02-02"), ("2024-02-03")) est sollicitée. Le système ignore les deux autres partitions, ce qui accélère considérablement la récupération des données.
SELECT * FROM orders WHERE order_time = '2024-02-02';
Utiliser le partitionnement par liste
Le partitionnement par liste organise les données selon les valeurs d'énumération des colonnes clés de partition. Lors de l'interrogation d'une table ainsi partitionnée, le système peut exclure les partitions non pertinentes grâce aux filtres, améliorant ainsi les performances.
Choisissez les colonnes clés de partition parmi les champs couramment utilisés pour gérer vos données métier. Veillez à répartir uniformément les données entre les partitions pour éviter tout déséquilibre significatif.
Prenons l'exemple d'un site e-commerce traitant un grand volume de commandes. Si vous souhaitez analyser ces commandes par ville de résidence des utilisateurs, spécifiez le champ customer_city comme clé de partition pour simplifier la gestion et les requêtes. Supposons que les données soient réparties géographiquement comme suit :
Pékin, Shanghai et Hong Kong, Chine : 6 Go
New York et San Francisco : 5 Go
Tokyo : 5 Go
Le code suivant illustre la création d'une table partitionnée par liste pour ces données de commande :
CREATE TABLE IF NOT EXISTS orders
(
`order_id` LARGEINT NOT NULL COMMENT "The order ID.",
`order_time` DATETIME NOT NULL COMMENT "The order time.",
`customer_city` VARCHAR(20) COMMENT "The city in which the user resides.",
`customer_id` LARGEINT NOT NULL COMMENT "The user ID.",
`total_amount` DOUBLE COMMENT "The total amount of the order.",
`status` VARCHAR(20) COMMENT "The order status.",
`payment_method` VARCHAR(20) COMMENT "The payment method.",
`shipping_method` VARCHAR(20) COMMENT "The shipping method.",
`customer_address` VARCHAR(500) COMMENT "The address of the user."
)
UNIQUE KEY(`order_id`, `order_time`, `customer_city`)
PARTITION BY LIST(`customer_city`)
(
PARTITION `p_cn` VALUES IN ("Beijing", "Shanghai", "Hong Kong"),
PARTITION `p_usa` VALUES IN ("New York", "San Francisco"),
PARTITION `p_jp` VALUES IN ("Tokyo")
)
DISTRIBUTED BY HASH(`order_id`) BUCKETS 16
PROPERTIES (
"enable_unique_key_merge_on_write" = "true"
);
Après la création de la table, exécutez l'instruction SQL suivante pour vérifier les partitions générées automatiquement (trois au total) :
SHOW partitions FROM orders;
p_cn: ("Beijing", "Shanghai", "Hong Kong")
p_usa: ("New York", "San Francisco")
p_jp: ("Tokyo")
Lors de l'exécution de la requête ci-dessous, seule la partition p_jp: ("Tokyo") est ciblée. Les deux autres partitions sont ignorées, ce qui optimise la vitesse d'interrogation.
SELECT * FROM orders WHERE customer_city = 'Tokyo';
Recourir au partitionnement dynamique
En environnement de production, une table peut comporter un nombre élevé de partitions, rendant leur gestion manuelle fastidieuse et coûteuse pour l'administrateur de la base de données. ApsaraDB for SelectDB permet de définir des règles de partitionnement dynamique dès la création de la table afin d'automatiser cette tâche.
Dans un contexte e-commerce, par exemple, il est fréquent d'interroger les tables de commandes par période et d'archiver les anciennes transactions. Vous pouvez alors utiliser le champ order_time comme clé de partition et activer le partitionnement dynamique dans la section PROPERTIES. L'exemple suivant montre comment configurer ce mécanisme : les paramètres dynamic_partition.time_unit, dynamic_partition.start et dynamic_partition.end permettent ici de créer des partitions journalières, de conserver uniquement les 180 derniers jours et d'anticiper la création des partitions pour les trois jours à venir.
Les parenthèses vides () à la fin de l'instruction PARTITION BY RANGE('order_time') () ne constituent pas une erreur de syntaxe. Elles sont obligatoires pour activer le partitionnement dynamique.
CREATE TABLE IF NOT EXISTS orders
(
`order_id` LARGEINT NOT NULL COMMENT "The order ID.",
`order_time` DATETIME NOT NULL COMMENT "The order time.",
`customer_id` LARGEINT NOT NULL COMMENT "The user ID.",
`total_amount` DOUBLE COMMENT "The total amount of the order.",
`status` VARCHAR(20) COMMENT "The order status.",
`payment_method` VARCHAR(20) COMMENT "The payment method.",
`shipping_method` VARCHAR(20) COMMENT "The shipping method.",
`customer_city` VARCHAR(20) COMMENT "The city in which the user resides.",
`customer_address` VARCHAR(500) COMMENT "The address of the user."
)
UNIQUE KEY(`order_id`, `order_time`)
PARTITION BY RANGE(`order_time`) ()
DISTRIBUTED BY HASH(`order_id`)
PROPERTIES (
"enable_unique_key_merge_on_write" = "true",
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.start" = "-180",
"dynamic_partition.end" = "3",
"dynamic_partition.prefix" = "p",
"dynamic_partition.create_history_partition" = "true",
"dynamic_partition.buckets" = "16"
);
Si votre table est susceptible de contenir un grand nombre de partitions, nous vous recommandons vivement de maîtriser le partitionnement dynamique. Pour plus d'informations, consultez Partitionnement dynamique.
Tablets
Le moteur de stockage d'ApsaraDB for SelectDB répartit les données en différents tablets selon la valeur de hachage d'une colonne spécifiée. Chaque tablet est géré par un nœud distinct du cluster, exploitant ainsi la puissance du système distribué pour traiter de gros volumes de données. Lors de la création d'une table, utilisez la clause DISTRIBUTED BY HASH('<Colonne clé du tablet>') BUCKETS <Nombre de tablets> pour configurer cette répartition. Pour plus de détails, reportez-vous à la section Bucketing de la rubrique « Partitionnement et bucketing ».
Remarques d'utilisation
Si le partitionnement est activé, la clause DISTRIBUTED... définit les règles de répartition au sein de chaque partition. Sinon, elle s'applique à l'ensemble des données de la table.
-
Plusieurs colonnes peuvent servir de clés de tablet.
Dans les modèles Aggregate et Unique, les clés de tablet doivent obligatoirement être des colonnes clés. Avec le modèle Duplicate, elles peuvent être indifféremment des colonnes clés ou des colonnes de valeur.
Privilégiez les colonnes à forte cardinalité comme clés de tablet afin d'assurer une répartition homogène des données et d'éviter les déséquilibres.
-
Théoriquement, le nombre de tablets n'est pas limité.
Bien qu'il n'y ait pas de limite théorique au volume de données par tablet, il est recommandé de viser une taille comprise entre 1 Go et 10 Go.
Des tablets trop petits multiplient leur nombre et alourdissent la gestion des métadonnées.
À l'inverse, des tablets trop volumineux compliquent la migration des réplicas et empêchent d'exploiter pleinement le cluster distribué. Cela augmente également le coût des tentatives en cas d'échec d'opérations effectuées au niveau du tablet, comme les modifications de schéma ou la création d'index.
Choisir une colonne clé de tablet
Le choix des colonnes clés de tablet lors de la conception de la table influence directement les performances et la concurrence des requêtes. Le tableau ci-dessous résume les règles de sélection. Si votre activité implique divers types de requêtes, plusieurs combinaisons de clés peuvent être nécessaires ; donnez alors la priorité aux besoins d'interrogation principaux.
Règle | Avantage |
Opter pour des colonnes à forte cardinalité ou combiner plusieurs colonnes afin de garantir une répartition uniforme des données | Les données sont mieux réparties sur les nœuds du cluster, permettant d'exploiter pleinement les ressources du système distribué. Cela améliore les performances des requêtes peu sélectives nécessitant l'analyse de grands volumes de données. |
Privilégier les colonnes fréquemment utilisées dans les conditions de filtrage pour concilier élagage des données et accélération des requêtes | Les données partageant la même valeur pour les colonnes clés de tablet sont regroupées. Cela accélère l'élagage et améliore la concurrence pour les requêtes ponctuelles utilisant ces colonnes comme filtres. Remarque Les requêtes ponctuelles servent généralement à extraire un petit ensemble de données répondant à des critères précis (filtrage par clé primaire ou colonne à forte cardinalité). Elles permettent de localiser et récupérer efficacement ces informations spécifiques. |
Exemple
Dans un scénario e-commerce, les requêtes portent majoritairement sur des commandes individuelles, bien que des analyses statistiques globales soient parfois nécessaires. Dans ce cas, choisissez la colonne à forte cardinalité order_id (parmi les colonnes clés de la table) comme clé de tablet. Cela garantit une répartition équitable des données sur plusieurs tablets et regroupe les informations liées à order_id, offrant ainsi les performances requises pour ces deux types de requêtes. Voici un exemple de création de table adaptée à ce contexte :
CREATE TABLE IF NOT EXISTS orders
(
`order_id` LARGEINT NOT NULL COMMENT "The order ID.",
`order_time` DATETIME NOT NULL COMMENT "The order time.",
`customer_id` LARGEINT NOT NULL COMMENT "The user ID.",
`total_amount` DOUBLE COMMENT "The total amount of the order.",
`status` VARCHAR(20) COMMENT "The order status.",
`payment_method` VARCHAR(20) COMMENT "The payment method.",
`shipping_method` VARCHAR(20) COMMENT "The shipping method.",
`customer_city` VARCHAR(20) COMMENT "The city in which the user resides.",
`customer_address` VARCHAR(500) COMMENT "The address of the user."
)
UNIQUE KEY(`order_id`, `order_time`)
PARTITION BY RANGE(`order_time`) ()
DISTRIBUTED BY HASH(`order_id`)
PROPERTIES (
"enable_unique_key_merge_on_write" = "true",
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.start" = "-7",
"dynamic_partition.end" = "3",
"dynamic_partition.prefix" = "p",
"dynamic_partition.create_history_partition" = "true",
"dynamic_partition.buckets" = "16"
);
Index
Les index jouent un rôle crucial dans la conception d'une base de données : bien choisis, ils améliorent considérablement les performances des requêtes. Toutefois, ils consomment de l'espace de stockage et peuvent ralentir les écritures. Cette section passe en revue les index courants pour vous aider à sélectionner ceux adaptés à vos besoins. Pour plus d'informations, consultez Vue d'ensemble des index.
Règles de création des index
Généralement, un index de préfixe est créé automatiquement sur une clé spécifique, offrant un filtrage optimal. Cependant, une table ne pouvant avoir qu'un seul index de préfixe, choisissez la clé la plus fréquemment utilisée comme condition de filtre.
Pour les autres besoins d'accélération du filtrage, privilégiez les index inversés. Polyvalents, ils acceptent des combinaisons de plusieurs colonnes comme conditions de filtre. Vous pouvez également utiliser des index Bloom filter légers et des index NGram Bloom filter pour les correspondances de chaînes (requêtes d'égalité et LIKE).
Sélectionner un index
Dans ApsaraDB for SelectDB, les tables disposent d'index intégrés ou personnalisés. Les premiers sont générés automatiquement par le système, tandis que les seconds peuvent être créés lors de la création de la table ou ultérieurement, selon vos besoins métier.
Méthode | Type d'index | Type de requête pris en charge | Type de requête non pris en charge | Avantage | Inconvénient |
Intégré | Index de préfixe |
|
| Peu gourmands en espace de stockage, les index de préfixe tiennent entièrement en mémoire, permettant une localisation rapide des blocs de données et un gain significatif de performance. | Une table ne peut comporter qu'un seul index de préfixe. |
Personnalisé | Index inversé (recommandé) |
| N/A | Prend en charge une grande variété de requêtes. Ces index peuvent être créés lors de la création de la table ou ultérieurement, et supprimés si nécessaire. | Consommation importante d'espace de stockage. |
Index Bloom filter | Requête d'égalité |
| Faible empreinte sur les ressources de calcul et de stockage. | Limité aux requêtes d'égalité. | |
Index NGram Bloom filter | Requête LIKE |
| Accélère les requêtes LIKE tout en consommant peu de ressources de calcul et de stockage. | Utile uniquement pour accélérer les requêtes LIKE. |
Utiliser des index
Utiliser un index inversé
ApsaraDB for SelectDB prend en charge les index inversés. Ceux-ci permettent d'effectuer des recherches plein texte sur des données de type TEXT, ainsi que des requêtes d'égalité ou par plage sur des champs classiques, facilitant ainsi la récupération rapide d'informations spécifiques au sein de grands volumes de données. Cette section explique comment créer un index inversé. Pour plus de détails, consultez Index inversé.
Créer un index inversé lors de la création de la table
Dans un scénario e-commerce, les recherches de commandes se font souvent par mots-clés tels que l'identifiant utilisateur ou l'adresse. Pour accélérer ces requêtes, créez un index inversé sur les champs customer_id et customer_address. L'exemple suivant illustre la création d'une table intégrant ces index :
CREATE TABLE IF NOT EXISTS orders
(
`order_id` LARGEINT NOT NULL COMMENT "The order ID.",
`order_time` DATETIME NOT NULL COMMENT "The order time.",
`customer_id` LARGEINT NOT NULL COMMENT "The user ID.",
`total_amount` DOUBLE COMMENT "The total amount of the order.",
`status` VARCHAR(20) COMMENT "The order status.",
`payment_method` VARCHAR(20) COMMENT "The payment method.",
`shipping_method` VARCHAR(20) COMMENT "The shipping method.",
`customer_city` VARCHAR(20) COMMENT "The city in which the user resides.",
`customer_address` VARCHAR(500) COMMENT "The address of the user.",
INDEX idx_customer_id (`customer_id`) USING INVERTED,
INDEX idx_customer_address (`customer_address`) USING INVERTED PROPERTIES("parser" = "chinese")
)
UNIQUE KEY(`order_id`, `order_time`)
PARTITION BY RANGE(`order_time`) ()
DISTRIBUTED BY HASH(`order_id`)
PROPERTIES (
"enable_unique_key_merge_on_write" = "true",
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.start" = "-7",
"dynamic_partition.end" = "3",
"dynamic_partition.prefix" = "p",
"dynamic_partition.create_history_partition" = "true",
"dynamic_partition.buckets" = "16"
);
Ajouter un index inversé à une colonne d'une table existante
Toujours dans un contexte e-commerce, supposons que vous deviez rechercher fréquemment des commandes par identifiant utilisateur, mais que l'index inversé sur le champ customer_id ait été omis lors de la création de la table orders. Exécutez alors l'instruction suivante pour ajouter cet index :
ALTER TABLE orders ADD INDEX idx_customer_id (`customer_id`) USING INVERTED;
Utiliser un index de préfixe
Un index de préfixe repose sur une ou plusieurs colonnes clés des données sous-jacentes, lesquelles sont triées selon ces colonnes. Il fonctionne essentiellement comme une recherche binaire tirant parti de ce tri. S'agissant d'index intégrés, SelectDB les génère automatiquement après la création de la table.
Aucune syntaxe spécifique ne permet de définir explicitement un index de préfixe. Le système sélectionne automatiquement les premiers champs de colonne clé de la table pour constituer cet index, dont la longueur totale ne peut excéder 36 octets. Tout champ de colonne clé situé après un champ de type VARCHAR est exclu de l'index de préfixe.
L'ordre des champs dans la table est donc déterminant, car il définit la composition de l'index de préfixe. Nous vous recommandons vivement de respecter les règles suivantes pour organiser vos colonnes clés :
Placez en tête les colonnes clés à forte cardinalité fréquemment utilisées comme filtres. Par exemple, dans la section Utiliser le modèle Duplicate, le champ
log_timeprécède le champerror_code.Priorisez les colonnes clés utilisées pour des filtres d'égalité avant celles servant aux filtres par plage. Ainsi, dans la section Utiliser un index inversé, le champ order_time (filtre par plage) apparaît après order_id.
Positionnez les champs de type ordinaire avant ceux de type VARCHAR. Par exemple, placez les colonnes clés de type INT avant celles de type VARCHAR.
Exemples
Reprenons l'exemple de la section Utiliser un index inversé, où la table des commandes bénéficie de l'index de préfixe order_id+order_time. Si la condition de requête inclut order_id seul ou combiné avec order_time, les performances s'améliorent nettement. Ainsi, la requête de l'Exemple 1 sera plus rapide que celle de l'Exemple 2.
Exemple 1
SELECT * FROM orders WHERE order_id = 1829239 and order_time = '2024-02-01';
Exemple 2
SELECT * FROM orders WHERE order_time = '2024-02-01';
Étapes suivantes
Après avoir suivi les trois premières étapes de ce tutoriel, vous possédez les bases d'ApsaraDB for SelectDB et savez concevoir des tables adaptées à vos besoins métier. Vous pouvez désormais explorer des opérations plus avancées telles que la migration de données, l'interrogation de sources externes ou la mise à jour du noyau. Pour plus d'informations, consultez Étapes suivantes.