Une donnée informatique est un élément d'information ayant subi un encodage numérique
Pour une gestion efficace des données, il est nécessaire de pouvoir identifier chaque enregistrement de façon unique.
L'indexation des données repose sur un principe simple d'étiquetage consistant à attribuer une étiquette différente à chaque enregistrement. Cette étiquette peut être une suite de caractères arbitraires, un entier, ou un descripteur explicite. On parle en général de clé ou d'identifiant pour désigner cette étiquette.
On peut représenter l'opération d'indexation sous la forme d'une fonction. Si d est le jeu de valeurs, k(d) désigne l'identifiant de ce jeu de valeurs.
L'existence d'un identifiant unique pour chaque jeu de valeurs d permet la mise en œuvre d'une recherche par identifiant (ou recherche par clé).
La recherche par identifiant repose sur une fonction d'adressage I qui à tout identifiant k associe sa position (entrée) i dans un tableau de données: I:k→i. Ainsi si k est l'identifiant servant à la recherche, l'extraction des informations se fait en 2 étapes:
L'identifiant doit en pratique tenir sur un nombre d'octets le plus petit possible pour que la liste L puisse être manipulée en mémoire centrale. Autrement dit, il faut que :
pour que :
Définir un ordre sur les données
La présence d'un identifiant permet de définir un ordre total sur les données :
Lier les données
Dans le cas des bases de données, l'identifiant constitue une référence vers les jeux de valeurs des tableaux de données. Une référence permet de lier les données d'une table aux données d'une autre table.
Exemple :
Structure d'ensemble
L'index définit l'appartenance d'une donnée à un ensemble.
Soit E un ensemble de données indexées : E={d1,d2,...,dK} On a l'équivalence : d∈E⇔k(d)∈I
Ainsi, il ne peut y avoir de doublon car ∀d :
L'exemple le plus simple d'indexation est celui fourni par les numéros de case d'un tableau.
Dans le cas général, l'identifiant n'est pas égal à l'entrée!
On sépare donc l'index k de l'entrée i:
Il existe différentes méthodes permettant d'assurer l'intégrité de l'index:
Utilisation d'une fonction de hachage :
Attribution d'un identifiant arbitraire entre 0 et n-1
i = int.from_bytes(d, byteorder='big')
s = 'paul.poitevin@centrale-marseille.fr' d = bytes(s, 'ascii') i = int.from_bytes(d, byteorder='big') print("i =", i)
donne :
i = 852806586114976881510056778471769180697471859150728801241505293627173168229624211058
k = H(i) = i mod n
j = i + 1
, H(j) = H(i) + 1
(presque toujours)paul.poitevin@centrale-marseille.fr
) = 1697539698
martin.mollo@centrale-marseille.fr
) = 1697539698
paul.poitevin@centrale-marseille.fr
) = 36148249469507
martin.mollo@centrale-marseille.fr
) = 65330032132071
k = H(i) = (i * m) mod n
j = i + 1
, j * m - i * m = m
i * m
peut etre coûteux à calculerj != i
tel que H(i) = H(j)
. Le gestionnaire de bases de données MongoDB utilise une indexation des données par clé cryptographique.
Que faire lorsque l'index ne tient pas en totalité dans la mémoire centrale ?
Considérons un index composé de couples (clé, numero de page). On suppose que l’index est également découpé en pages, chaque page d'index contenant au maximum b clés. Si l’index comporte beaucoup de pages, il est intéressant de l’organiser hiérarchiquement en pages et sous-pages, selon une organisation appelée "B-arbre" (Balanced Tree):
I ← charger la racine de l’arbre tant que I n’est pas une feuille : k’ ← première clé de I tant que k > k’ k’ ← clé suivante I ← charger sous-page de k’
Remarque : Pour que l’accès aux données soit efficace,
b
fils, En pratique, il existe des algos permettant d’assurer que chaque noeud contient entre b/2 et b clés (sauf la racine).
On introduit dans ce chapitre le modèle relationnel qui sert de fondation à la conception de bases de données.
Les différents modèles utiles en représentation des connaissances reposent sur des notions de base de la théorie des ensembles :
Schémas de données
Tableau de données
Un tableau de données est une liste (finie et ordonnée) de tuples, chaque tuple obéissant à un même schéma R.
UML :
Client(nom, prénom, adresse, âge)
Étudiant(nom, prénom, adresse, INE)
Ouvrage(titre, auteur, éditeur, prix, date_édition)
Véhicule(immatriculation, marque, modèle, couleur)
Aj:E→Dj x↦Aj(x)
Un ensemble d'entités est un ensemble fini d'éléments : E={x1,…,xn} Il regroupe (ou associe) plusieurs entités ayant des caractéristiques communes (descriptibles à l'aide du même ensemble d'attributs).
R:X→D1×...×Dm xi↦(A1(xi),…,Am(xi))
La Relation est la représentation logique d'un tableau de données.
Un tableau de données est une liste (finie et ordonnée) de tuples, chaque tuple obéissant à un même schéma R.
Soit R=(A1,...,Am) un schéma de données
Une relation r obéissant au schéma R est un sous-ensemble du produit cartésien dom(A1)×...×dom(Am)
Soit la relation r:
A | B | C |
---|---|---|
1 | a | e |
2 | b | f |
2 | c | f |
3 | d | k |
4 | d | k |
F={num_client, date→num_article, quantité, prixnum_article, quantité→prix}
La contrainte signifie :
Exprimer la dépendance fonctionnelle :
Soit le schéma relationnel suivant :
Billet(num_train, type_train, num_voiture, num_place, date, id_passager, nom_passager, prénom_passager, date_naissance, gare_départ , horaire_départ, gare_arrivée, horaire_arrivée, classe, tarif)
Définir des dépendances fonctionnelles sur cet ensemble d'attributs
Représentation UML :
Soit K une clé candidate. On démontre que K→R à l'aide des axiomes d'Amstrong à partir d'un ensemble de DF connues:
Soit le schéma relationnel suivant :
Billet(num_train, type_train, num_voiture, num_place, date, id_passager, nom_passager, prénom_passager, date_naissance, gare_départ , horaire_départ, gare_arrivée, horaire_arrivée, classe, tarif)
Montrer que l'ensemble {num_train, num_voiture, num_place, date, gare_départ} est une clé primaire du schéma?
Tables mal construites
Fournisseur(nom_f, composant_,adresse_f, prix)
–> Impossible de retrouver les prix pratiqués par les différents fournisseurs.
–> Il est possible de reconstruire la table initiale en effectuant une jointure entre ces 2 tables sur l’attribut nom_f
.
Les Formes normales
R(A1,...,Ai,...,An_,B1,...,Bj,...,Bm)
AiDFE→Bj A1,...,Ai,...,AnDFE→B1,...,Bj−1,Bj+1...,Bm
R1(A1,...,Ai,...,An_,B1,...,Bj−1,Bj+1...,Bm) R2(Ai_,Bj)
Même si aucun attribut ne dépend plus de la clé primaire initiale, il est important de la conserver dans une table spécifique (elle sert à “lier” les valeurs dispersées dans les différentes tables).
Fournisseur(nom_f,composant_,adresse_f, prix) nom_f→adresse_f nom_f, composant→prix
Catalogue(nom_f,composant_,prix) Fournisseur(nom_f_,adresse_f)
La dépendance fonctionnelle entre 2 attributs Ai et Aj est directe s’il n’existe pas de Ak tel que : Ai→Ak→Aj
Un schéma est 3FN :
Commande(num_commande_,nom_f, adresse_f, composant, quantité) num_commande→nom_f, composant, quantité nom_f→adresse_f
Le schéma n’est pas 3FN!! (dépendance transitive entre num_commande et adresse)
* Lorsqu’un schéma relationnel n’est pas en troisième forme normale, il doit être normalisé:
Soit : R(A1,...,Am_,B1,...,Bi,...,Bj,...,Bn) avec : A1,...,AmDFD→B1,...,Bi,...,Bj−1,Bj+1,...,Bn BiDFD→Bj Alors : R1(A1,...,Am_,B1,...,Bi,...,Bj−1,Bj+1,...,Bn) R2(Bi_,Bj)
Comme précédemment, il est important de conserver la clé primaire de la table initiale si elle permet d'associer les valeurs dispersées dans les tables.
Avant :
Après :
L’attribut nom_f est maintenant clé primaire de la table Client et clé étrangère de la table Commande.