1. Concept et Application de l'Index
1.1 Qu'est-ce qu'un Index
Un index est une structure de données utilisée dans un système de gestion de base de données pour accélérer les opérations de récupération de données. On peut le voir comme un "répertoire" dans la base de données, permettant de localiser rapidement des données dans une table de données, évitant les analyses complètes de table, et améliorant significativement l'efficacité des requêtes. Dans des applications pratiques, l'utilisation correcte des index peut grandement améliorer les performances d'une base de données.
1.2 Types d'Indexes
Il existe différents types d'index, chacun ayant sa propre conception et son optimisation pour différents scénarios d'application :
- Index à Champ Unique : Un index qui inclut uniquement un champ, adapté aux scénarios qui reposent sur une condition unique pour des requêtes rapides.
- Index Composite : Un index qui inclut plusieurs champs, offrant une optimisation pour les requêtes contenant ces champs.
- Index Unique : Assure l'unicité des champs d'index, interdisant l'existence de valeurs en double. Les index uniques peuvent être à champ unique ou composite.
2. Définition de l'Index
2.1 Définition de l'Index de Champ
La création d'un index à champ unique implique d'établir un index sur une colonne spécifique d'une table de données, ce qui peut être réalisé à l'aide de la méthode Fields
. L'exemple suivant montre comment créer un index sur le champ phone
de l'entité Utilisateur
.
func (Utilisateur) Fields() []ent.Field {
return []ent.Field{
field.String("phone"),
}
}
func (Utilisateur) Indexes() []ent.Index {
// Créer un index à champ unique.
return []ent.Index{
index.Fields("phone"),
}
}
Dans cet extrait de code, le champ phone
est indexé. Cela permet au système d'utiliser l'index pour des recherches plus rapides lors de la requête du champ phone
.
2.2 Définition de l'Index Unique
Un index unique assure l'unicité des données sur les colonnes indexées. Il peut être créé en ajoutant la méthode Unique
au champ. Les exemples suivants illustrent la création d'index uniques pour un champ unique et pour plusieurs champs.
Créer un index unique pour un champ unique :
func (Utilisateur) Fields() []ent.Field {
return []ent.Field{
field.String("email").Unique(),
}
}
Dans cet exemple, le champ email
est spécifié comme unique, garantissant que chaque adresse e-mail d'utilisateur est unique dans la base de données.
Créer un index unique pour une combinaison de plusieurs champs :
func (Utilisateur) Indexes() []ent.Index {
return []ent.Index{
// Créer un index unique pour plusieurs champs.
index.Fields("first_name", "last_name").Unique(),
}
}
Ce code définit un index unique composite pour la combinaison des champs first_name
et last_name
, empêchant l'apparition d'enregistrements avec les mêmes valeurs dans les deux champs.
2.3 Définition de l'Index Composite
Lorsque les conditions de requête impliquent plusieurs champs, un index composite peut entrer en jeu. L'index composite stocke les données dans l'ordre défini dans l'index. L'ordre de l'index a un impact significatif sur les performances des requêtes, c'est pourquoi lors de la définition d'un index composite, l'ordre des champs doit être déterminé en fonction du schéma de requête.
Voici un exemple de création d'un index composite :
func (Utilisateur) Indexes() []ent.Index {
return []ent.Index{
// Créer un index composite avec plusieurs champs.
index.Fields("country", "city"),
}
}
Dans cet exemple, un index composite est créé sur les champs country
et city
. Cela signifie que lors d'opérations de requête impliquant ces deux champs, la base de données peut rapidement localiser les données qui répondent aux conditions.
Un index composite ne se contente pas d'accélérer les performances des requêtes, il prend également en charge les opérations de tri basées sur l'index, offrant des performances de récupération de données plus efficaces. Lors de la conception d'un index composite, il est courant de placer les champs avec une plus grande sélectivité en tête de l'index, afin que l'optimiseur de base de données puisse mieux utiliser l'index.
3. Index des arêtes
Dans le framework ent, les index des arêtes sont une façon de définir des index via les arêtes (relations). Ce mécanisme est généralement utilisé pour assurer l'unicité des champs sous des relations spécifiques. Par exemple, si votre modèle de base de données inclut des villes et des rues, et que chaque nom de rue sous une ville doit être unique, les index des arêtes peuvent être utilisés pour y parvenir.
// Le fichier ent/schema/street.go définit le schéma de l'entité Street.
type Street struct {
ent.Schema
}
func (Street) Fields() []ent.Field {
// Définir les champs
return []ent.Field{
field.String("name"),
}
}
func (Street) Edges() []ent.Edge {
// Définir la relation d'arête avec City, où Street appartient à une City.
return []ent.Edge{
edge.From("city", City.Type).
Ref("streets").
Unique(),
}
}
func (Street) Indexes() []ent.Index {
// Créer un index unique à travers l'arête pour assurer l'unicité des noms de rue au sein de la même ville.
return []ent.Index{
index.Fields("name").
Edges("city").
Unique(),
}
}
Dans cet exemple, nous créons une entité Street
et l'associons à l'entité City
. En définissant un index d'arête dans la méthode Indexes
de l'entité Street
, nous assurons que le nom de chaque rue sous une ville est unique.
Chapitre 5 : Options d'index avancées
5.1 Indexes de texte intégral et de hachage
Les index de texte intégral et les index de hachage sont deux types d'index uniques dans MySQL et PostgreSQL, et ils sont utilisés pour différents scénarios d'optimisation de requêtes.
L'index de texte intégral est couramment utilisé pour la recherche de données textuelles, en particulier lorsque vous devez effectuer des recherches complexes, telles que des recherches par correspondance de mots. Les bases de données MySQL et PostgreSQL prennent en charge l'indexation de texte intégral. Par exemple, dans MySQL, vous pouvez définir un index de texte intégral comme ceci :
// Le fichier ent/schema/user.go définit le schéma de l'entité User
func (User) Indexes() []ent.Index {
// Créer un index de texte intégral en utilisant la catégorie FULLTEXT dans MySQL
return []ent.Index{
index.Fields("description").
Annotations(entsql.IndexTypes(map[string]string{
dialect.MySQL: "FULLTEXT",
})),
}
}
L'index de hachage est particulièrement adapté pour les requêtes d'égalité et ne prend pas en charge le tri et les requêtes de plage. Dans PostgreSQL, vous pouvez utiliser un index de hachage comme ceci :
func (User) Indexes() []ent.Index {
// Définir un index de type HASH
return []ent.Index{
index.Fields("c4").
Annotations(entsql.IndexType("HASH")),
}
}
5.2 Indexes partiels et préfixes d'index
L'index partiel est un type d'index qui indexe uniquement les lignes dans une table qui satisfont des conditions spécifiques. Dans SQLite et PostgreSQL, vous pouvez utiliser la clause WHERE pour créer des index partiels.
Par exemple, définir un index partiel dans PostgreSQL :
func (User) Indexes() []ent.Index {
// Créer un index partiel sur le champ "nickname", contenant uniquement les lignes où "active" est vrai
return []ent.Index{
index.Fields("nickname").
Annotations(
entsql.IndexWhere("active"),
),
}
}
Le préfixe d'index est particulièrement utile pour les champs de texte, notamment dans MySQL. Il permet de réduire le temps de création de l'index, de réduire l'espace occupé par l'index et d'offrir de bonnes performances. Comme le montre l'exemple ci-dessous, pour MySQL, vous pouvez définir un index avec un préfixe :
func (User) Indexes() []ent.Index {
// Créer un index en utilisant un préfixe d'index
return []ent.Index{
index.Fields("description").
Annotations(entsql.Prefix(128)),
}
}
5.3 Annotations d'index et personnalisation
Dans ent, les Annotations
sont une fonctionnalité qui permet aux développeurs de personnaliser les index. Vous pouvez définir le type d'index, définir des règles de tri, et plus encore.
Par exemple, le code suivant montre comment spécifier les règles de tri des colonnes dans un index :
func (User) Indexes() []ent.Index {
return []ent.Index{
// Utiliser des annotations pour définir les règles de tri des colonnes de l'index
index.Fields("c1", "c2", "c3").
Annotations(entsql.DescColumns("c1", "c2")),
}
}
Avec la fonctionnalité d'annotation, les développeurs peuvent personnaliser de manière flexible les index pour optimiser les performances et la structure de la base de données.