tc_info:cm5

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
tc_info:cm5 [2018/12/04 10:42] edaucetc_info:cm5 [2024/06/28 15:18] (Version actuelle) – modification externe 127.0.0.1
Ligne 1: Ligne 1:
 +
 +
 +==== CM5 : Indexation / Modèle relationnel ====
 +
 +
 +=====5. L'indexation=====
 +
 +<note tip> **Rappel **
 +
 +Une //donnée informatique// est un élément d'information ayant subi un encodage numérique
 +    * Consultable/manipulable/échangeable par des programmes informatiques
 +    * Possibilité de la conserver sur un support de stockage numérique (CD-ROM, disque dur, SSD, ...)
 +      * Les informations peuvent être stockés dans un fichier (ex : fichier csv).
 +    * Un jeu de valeurs encodé et enregistré est appelé un //enregistrement//
 +
 +
 +</note>
 +
 +==== 5.1 Généralités ====
 +
 +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. 
 +
 +  * L'**indexation** des données consiste  à attribuer à chaque donnée distincte un **identifiant** unique. 
 +  * On parle également  de //clé// de l'enregistrement:
 +
 +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.
 +
 +=== Unicité ===
 +
 +<note important>
 +  * soient d1 et d2 deux enregistrements, 
 +  * si k(d1)=k(d2), alors d1=d2.
 +</note>
 +
 +=== Efficacité ===
 +
 +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:ki.
 +Ainsi si k est l'identifiant servant à la recherche, l'extraction des informations se fait en 2 étapes:
 +  * i=I(k) (lecture de l'index des données)
 +  * d=D[i] (lecture des données elles mêmes)
 +
 +<note tip>
 +La lecture de l'index repose sur le parcours d'une liste 
 +L=((k1,i1),(k2,i2),...,(kN,iN)) telle que k1<k2<...<kN, de telle sorte que la recherche s'effectue en O(log N) (recherche dichotomique).
 +</note>
 +
 +=== Compacité ===
 + 
 +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 :
 +  * |k|<<|d|
 +pour que :
 +  * |L|<<|D|
 +
 +<note tip>
 +Un identifiant entier, codé sur 4 octets, permet d'indexer jusqu'à 24×84×109 données différentes. 
 +</note>
 +
 +
 +=== Utilisation ===
 +
 +** 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 :
 +  * ordre sur les entiers (identifiant entier)
 +  * ordre alphabétique (identifiant texte)
 +  * ordre //ASCII//bétique (chaîne de caractères quelconque)
 +
 +** 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 :__
 +  * {{http://edauce.perso.centrale-marseille.fr/visible/Artists.csv|Artistes}}
 +  * {{http://edauce.perso.centrale-marseille.fr/visible/Albums.csv|Albums}}
 +  * {{http://edauce.perso.centrale-marseille.fr/visible/Track.csv|Pistes}}
 +
 +  * Pour chaque album de la table des albums, l'identifiant d'artiste (ici un numéro) permet de lier l'album avec l'artiste (ou groupe) correspondant.  
 +  * Pour chaque piste de la table des pistes,  l'identifiant d'album permet de lier la piste à l'album correspondant (et donc à l'artiste correspondant par transitivité) 
 +
 +<note>
 +**Exercice** : donner le nom du groupe qui interprète la piste '//Paradise City//'.
 +</note>
 +
 +
 +** 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 :
 +dEk(d)I
 +
 +Ainsi, il ne peut y avoir de doublon car d :
 +  * k(d) est unique
 +  * i=I(k(d)) est unique ssi dE et indéfini sinon.
 +==== 5.2 Exemples d'indexation des données ====
 +
 +=== 5.2.1 Adressage des tableaux ===
 +
 +L'exemple le plus simple d'indexation est celui fourni par les **numéros de case** d'un tableau.
 +  * Soit D un tableau de n lignes
 +  * le numéro i<n est à la fois l'identifiant et l'//entrée// (ou //adresse//) de la ligne D[i]
 +
 +{{https://wiki.centrale-marseille.fr/informatique/_media/public:std-3:cm1:aspect_physique:s7_index.png}}
 +
 +=== 5.2.2 Maintenance centralisée d'un index===
 +
 +**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:
 +  * k est l'identifiant (ou clé) de la donnée d. Il s'agit d'une valeur numérique quelconque.
 +  * i est l'entrée de la donnée d, correspondant à sa position dans le tableau de données. 
 +
 +<note important>
 +Lors de l'ajout de nouvelles données, il est nécessaire de définir une méthode permettant d'assurer:
 +  * l'//intégrité// de l'index
 +  * l'unicité de l'identifiant 
 +</note>
 +
 +Il existe différentes méthodes permettant d'assurer l'intégrité de l'index:
 +  * Le programme maintient une liste triée des identifiants déjà utilisées. Lors de l'ajout d'une nouvelle donnée, il s'assure que l'identifiant n'est pas déjà présente dans la liste.
 +    * Coût :
 +      * O(n) en mémoire
 +      * O(logn) pour l'ajout 
 +  * Dans le cas où les identifiants sont des numéros (entiers), il est possible d'utiliser un compteur qui s'incrémente à chaque nouvelle insertion.
 +    * Coût :
 +      * O(1) en mémoire
 +      * O(1) pour l'ajout
 +
 +<note>
 +**Exemples d'indexation centralisée** :
 +  * numéro INE (étudiants)
 +  * numéro URSSAF (sécurité sociale)
 +  * numéro d'immatriculation (véhicules)
 +  * numéro de compte en banque
 +  * code barre
 +  * etc.
 +</note>
 +
 +
 +=== 5.2.3 Indexation pseudo-aléatoire : les fonctions de hachage ===
 +Utilisation d'une //fonction de hachage// :
 +  * qui "calcule" la valeur de l'identifiant à partir des valeurs du jeu de valeurs à insérer. 
 +  * La fonction de hachage doit être telle que la probabilité de choisir le même identifiant pour deux données différentes soit extrêmement faible.
 +
 +Attribution d'un identifiant arbitraire entre 0 et n-1
 +  * Etape 1 : **transcodage** binaire des données 
 +      * ''i = int.from_bytes(d, byteorder='big')''
 +      * avantage : les données différentes ont un code entier différent
 +      * mais : |i| = |d|
 +<code python>
 +s = 'paul.poitevin@centrale-marseille.fr'
 +d = bytes(s, 'ascii')
 +i = int.from_bytes(d, byteorder='big')
 +print("i =", i)
 +</code>
 +donne :
 +<code>
 +i = 852806586114976881510056778471769180697471859150728801241505293627173168229624211058
 +</code>
 +  * Etape 2 : **réduction** du code
 +    * __Méthode 1__ : le modulo n (reste de la division entière par n)      
 +      * ''k = H(i) = i mod n''
 +      * Avantage :
 +        *  |k|<<|d|
 +      * Inconvénient:
 +        * deux données différentes peuvent avoir le même code
 +        * ce codage revient à sélectionner les bits de poids faible
 +        * deux données proches ou très similaires auront un index proche ou similaire : si ''j = i + 1'', ''H(j) = H(i) + 1'' (presque toujours)
 +        * ---> il faut prendre n //premier//
 +
 +  *
 +    *
 +      * n=232=4294967296 :
 +        * H_code(''paul.poitevin@centrale-marseille.fr'') = ''1697539698''
 +        * H_code(''martin.mollo@centrale-marseille.fr'') = ''1697539698''
 +      * n=67280421310721 (premier):
 +        * H_code(''paul.poitevin@centrale-marseille.fr'') = ''36148249469507''
 +        * H_code(''martin.mollo@centrale-marseille.fr'') = ''65330032132071''
 +
 +  *
 +    * __Méthode 2__ : combiner produit et modulo -- soient m et n deux nombres premiers entre eux 
 +      * ''k = H(i) = (i * m) mod n''
 +      * Avantage :
 +        * |k|<<|d|
 +        * deux entiers proches donneront auront des codes très différents :  si ''j = i + 1'', ''j * m - i * m = m''
 +      * Inconvénient :
 +        * deux données différentes peuvent avoir le même code          
 +          * le produit ''i * m'' peut etre coûteux à calculer
 +
 +    * __Méthode 3__ : Hachage cryptographique : 
 +      * Le hachage cryptographique est construit de telle sorte qu'il soit très difficile de trouver un entier ''j != i'' tel que ''H(i) = H(j)''
 +      * Un tel code est appelé une "signature".
 +        * Exemples :
 +          * {{https://fr.wikipedia.org/wiki/MD4|MD4}}
 +          * {{https://fr.wikipedia.org/wiki/Secure_Hash_Algorithm|SHA}}
 +
 +=== Exemple ===
 +
 +Le gestionnaire de bases de données {{https://openclassrooms.com/fr/courses/1915371-guide-de-demarrage-pour-utiliser-mongodb|MongoDB}} utilise une indexation des données par clé cryptographique.
 +
 +==== 5.3 Généralisation : multi-indexation ====
 +
 +<note tip>
 +TODO
 +</note>
 +
 +==== 5.4 Structures de données pour l'indexation ====
 +
 +=== 5.4.1 Liste triée ==
 +<note tip>
 +TODO
 +</note>
 +
 +=== 5.4.2 Index bitmap ===
 +<note tip>
 +TODO
 +</note>
 +
 +=== 5.4.3 Les B-arbres ===
 +Que faire lorsque l'index ne tient pas en totalité dans la mémoire centrale ?
 +  * L'index est découpé en "blocs"
 +  * Les blocs sont organisés sous la forme d'un arbre (B-arbre = "//Balanced Tree//")
 +
 +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//):
 +      
 +{{ restricted:std-3:td1:b-tree.png}}
 +
 +  * chaque noeud de l’arbre contient une liste croissante de couples (clé, numéro d’une sous-page)
 +  * chaque clé est dupliquée dans sa sous-page : 
 +        * les clés contenues dans la sous-page sont inférieures ou égales à elle, 
 +        * les clés contenues dans la sous-page sont strictement supérieures à celles de la sous-page précédente.
 +        * les feuilles contiennent des couples (clé, numéro de la page du tableau de données)
 +
 +<note> **algo : lecture de l'Index**
 +  * paramètre d’entrée : k 
 +
 +  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’
 +</note>
 +
 +Remarque : Pour que l’accès aux données soit efficace, 
 +  * il faut que l’arbre soit le moins profond possible : arbre “équilibré”. 
 +  * Dans ce cas, 
 +    * chaque noeud a ''b'' fils, 
 +    * et la profondeur de l’arbre est de l’ordre de logb(N). 
 +  * Pour charger la page contenant le tuple cherché, 
 +    * il faut donc logb(N) + 1 lectures sur disque.
 +    * 
 +En pratique, il existe des algos permettant d’assurer que chaque noeud contient entre b/2 et b clés (sauf la racine). 
 +<note tip>
 +Voir : 
 +  * http://fr.wikipedia.org/wiki/Arbre_B
 +  * http://en.wikipedia.org/wiki/B-tree)
 +</note>
 +
 +===== 6. Le modèle relationnel =====
 +
 +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 :
 +    * Ensemble finis
 +    * Éléments partiellement (ou totalement) discernables
 +
 +==== 6.1 Schéma de données ====
 +
 +<note tip>
 +**//Rappel// : Organisation des données sous forme de tableaux bidimensionnels **
 +
 +** Schémas de données **
 +
 +  * Un enregistrement est un jeu de valeurs organisé sous forme de **tuple**
 +  * A un tuple on associe  en général  un **schéma de données**.
 +{{public:std-3:cm1:s7_schema.png}}
 +
 +  * Définir un **schéma** consiste à définir :
 +    * une liste d'attributs (labels) associées à chacune des valeurs du tuples. 
 +  * A chaque **attribut** correspond :
 +    * un //intitulé//
 +    * un //domaine// de valeurs (type/format des 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.
 +
 +{{https://wiki.centrale-marseille.fr/informatique/_media/public:std-3:cm1:s7-tableau-data.png}}
 +
 +</note>
 +
 +
 +  * Soit R(A1,...,Am) un schéma. 
 +  * On note dom(Ai) le domaine associé à l'attribut Ai.
 +  * On dit d'un tuple t qu'il //obéit au schéma R// si les valeurs qu'il contient correspondent aux domaines des attributs du schéma.  
 +
 +
 +
 +<note>
 +** Diverses représentations :**
 +
 +__[[public:STD-3:CM1:Aspect logique:2.2.2 Relation:Ensembles d'entités et schémas d'ensembles|Entité/association]]__ :
 +
 +{{public:std-3:cm1:s7-schema-merise.png}}
 +
 +__[[public:mco-2:paradigme_objet_et_modelisation_uml|UML]]__ : 
 +
 +{{public:std-3:cm1:s7_schema_uml.png}}
 +
 +__[[public:STD-3:CM1:Aspect logique:2.2.2 Relation|Schéma relationnel]]__ :
 +
 +**Client**(nom, prénom, adresse, âge) 
 +
 +</note>
 +
 +
 +<note> 
 +** __Exemples de schémas relationnels__ :**
 +
 +**Étudiant**(nom, prénom, adresse, INE)
 +
 +**Ouvrage**(titre, auteur, éditeur, prix, date_édition)
 +
 +**Véhicule**(immatriculation, marque, modèle, couleur)
 +</note>
 +
 +=== 6.1.1 Entité et attributs===
 +
 +  * Une **entité** x 
 +    * est une représentation d'un objet du monde réel, 
 +    * appartenant au système/à l'organisation modélisée. 
 +  * Une entité est décrite par une ou plusieurs valeurs caractéristiques, appelées **attributs**.
 +
 +<note important>
 +Les informations conservées au sujet des entités d'un ensemble sont les **attributs**.
 +  * Chaque **attribut** :
 +    * a un **nom** unique dans le contexte de cet ensemble d'entités : A, B, C, A1, A2, ..., Am, ...
 +      * Exemples de noms concrets : //couleur//, //nom//, //horaire//, //salaire//.
 +    * prend ses valeurs dans un domaine bien spécifié, 
 +      * également appelé le **type** de l'attribut. 
 +      * Le domaine d'un attribut est noté dom(Aj)=Dj.
 +        * Exemples :
 +          * dom(couleur)=rouge,vert,bleu,jaune
 +          * dom(nom)=ensemble des chaînes de caractères, 
 +          * dom(salaire)= entiers naturels 
 +          * etc...
 +    * Un attribut Aj est une fonction à valeur sur Dj :
 +Aj:EDj
 +xAj(x)
 +</note>
 +    * Un attribut peut être : 
 +      * simple ou composé.
 +        * Exemple :  une //adresse// peut être décrite par une simple chaîne de caractères, ou peut être décomposée en //rue// , //no//, //boîte//, //ville//, //code postal//, //pays//.
 +      * obligatoire ou facultatif (Dj peut ou non contenir la valeur ø ).
 +      * atomique ou non (Un attribut peut posséder 0, 1 voire plusieurs valeurs...)
 +
 +=== 6.1.2 Ensembles d’entités et schéma d’ensemble===
 +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).
 +
 +<note tip>
 +**Exemples** :
 +  * les employés d'une firme,
 +  * les cours de Centrale Méditerranée,
 +  * une collection de disques,
 +  * etc…
 +</note>
 +
 +  * Les éléments d’un ensemble d’entités sont //partiellement discernables// à travers les valeurs de leurs attributs : 
 +    * les attributs (A1,...,Am) servent à décrire les éléments de l’ensemble. 
 +    * Le schéma R de l’ensemble E est une //application// de l'ensemble d'entités vers l'ensemble des tuples de schéma R
 +      * Soit :
 +R:XD1×...×Dm
 +xi(A1(xi),,Am(xi))
 +
 +<note tip>
 +** représentation graphique ** :
 +
 +{{public:std-3:cm1:s7-entite-0.png}}
 +
 +</note>
 +
 +<note>
 +** Exemples **:
 +
 +{{public:std-3:cm1:s7-entite-01.png}}
 +
 +
 +</note>
 +
 +=== 6.1.3 Relation ===
 +
 +La **Relation** est la représentation logique d'un **tableau de données**.
 +
 +<note important>
 +**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.
 +
 +{{https://wiki.centrale-marseille.fr/informatique/_media/public:std-3:cm1:s7-tableau-data.png}}
 +</note>
 +
 +<note important>
 +**Définition**
 +
 +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) 
 +</note>
 +
 +<note tip>
 +**Corollaire** : une relation est un **ensemble** de tuples :
 +r={t1,...,tn}={(a11,...,a1m),...,(an1,...,anm)}
 +
 +  * avec :
 +    * (i,j),aijdom(Aj),
 +    * i,tidom(A1)×...×dom(Am)
 +    * n : nombre de tuples
 +    * m : nombre d'attributs par tuple
 +</note>
 +
 +<note tip>
 +**Remarque :**
 +  * Le **schéma** R représente le niveau abstrait (modélisation)
 +  * La **relation** r représente un cas concret de réalisaton (à un schéma R peuvent correspondre une infinité de réalisations possibles : r, r, r, etc. )
 +</note>
 +
 +==== 6.2 Dépendances fonctionnelles ====
 +
 +  * Au sein d'un schéma R
 +    * Il peut exister un ensemble de contraintes, noté F
 +      * portant sur les attributs (plus précisément sur les valeurs prises par les attributs). 
 +      * L'ensemble F est indépendant de R.
 +    * On parle de **contraintes d’intégrité**.
 +      * Ces contraintes s’expriment sous la forme de **dépendances fonctionnelles**.
 +
 +<note>
 +**Rappels d’algèbre de base:**
 +
 +  * **Relation binaire** : une relation binaire r portant sur deux domaines A et B:
 +    * est un sous-ensemble du produit cartésien A×B.
 +    * si (a,b)r, on note parfois arb ce qui signifie “a est en relation avec b”.
 +  * **Fonction** : une fonction f:AB est une relation binaire sur A×B telle que 
 +    * pour tout aA,
 +    * il existe un unique b tel que (a,b)f.
 +    * On note b=f(a)
 +      * ce qui signifie qu'au sein de la relation f, b est déterminé de façon unique par le choix de a (autrement dit : “b dépend de a”)
 +</note>
 +
 +<note important>
 +**Dépendance fonctionnelle**
 +
 +  * Soit r une relation définie selon R(A1,...,Am)
 +  * Soient X et Y deux sous-ensembles de R  
 +  * On dit que la relation r définit une //dépendance fonctionnelle// de X vers Y,  
 +    * notée XrY
 +    * si les valeurs de r permettent de définir une fonction de d(X) vers d(Y).
 +</note>
 +
 +<note tip>
 +**__Exemple 1__** :
 +
 +Soit la relation r:
 +^ A ^ B ^ C ^
 +| 1 | a | e |
 +| 2 | b | f |
 +| 2 | c | f |
 +| 3 | d | k |
 +| 4 | d | k |
 +
 +  * On a les dépendances suivantes :
 +    * AC
 +    * BC
 +    * mais pas : AB, BA, ni CA
 +  * On a aussi :
 +    * A,BC
 +    * mais pas : B,CA, ni A,CB, etc.
 +</note>
 +
 +<note tip>
 +**__Exemple 2__** :
 +
 +  * Soit le schéma : 
 +    * **Commande** (num_client, quantité, prix, date, num_article)
 +  * et l’ensemble de contraintes 
 +$$ \begin{array}{rl}F &= \{\\ 
 +    & \text{num_client, date} \rightarrow \text{num_article, quantité, prix} \\
 +    & \text{num_article, quantité} \rightarrow \text{prix} \\
 +    &\}
 +    \end{array}
 +$$
 +  * La première contrainte indique qu'il ne peut y avoir deux factures émises pour un même client à une date donnée.
 +  * La seconde contrainte indique que le prix payé dépend de l’article et de la quantité commandée.
 +</note>
 +
 +<note tip>
 +**__Exemple 3__** :
 +  * Soit le schéma : 
 +    * **Ouvrage** (titre, auteur, éditeur, prix, date_edition)
 +  * et la contrainte :
 +    * {titre, auteur, éditeur →  prix, date_édition}
 +La contrainte signifie : 
 +  * “//pour une oeuvre chez un certain éditeur, une seule édition est possible (pas de réédition à une date ultérieure)//
 +  * “//politique du prix unique//”
 +
 +</note>
 +
 +<note>
 +**Exercice :**
 +Soit le schéma :
 +
 +  *  **Réservation**(code_appareil, date, heure, salle)
 +
 +Exprimer la dépendance fonctionnelle : 
 +  * « //Un appareil ne peut pas être utilisé dans deux locaux différents au même moment //»
 +</note>
 +
 +  * Il importe donc de bien réfléchir, au moment de l'étape de conception, 
 +    * du réalisme et du caractère limitant de certaines dépendances fonctionnelles, 
 +    * et du caractère éventuellement limitant du choix des attributs.
 +  * Ainsi, le schéma décrivant les commandes (exemple 2) 
 +    * ne permet pas de commander des articles de nature différente au sein d'une même commande 
 +    * (un client, pour commander deux râteaux et une truelle, doit donc effectuer deux commandes, qui plus est à des dates différentes!).
 +
 +<note> ** Exercice **
 +
 +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
 +</note>
 +====6.3 Clé d'une relation====
 +
 +=== 6.3.1 Définitions ===
 +  * Soit un schéma R(A1,...,Am).
 +<note important>
 +**Clé**
 +
 +  * Une **clé** K :
 +    * est un ensemble **minimal** d'attributs inclus dans R,
 +    * tel que toute relation r de schéma R définit une dépendance fonctionnelle de d(K) dans d(R),
 +  * cette dépendance est notée KR.
 +</note>
 +<note>
 +  * **Remarques** :
 +    * Si un schéma R possède une clé K, alors tous les éléments d’une relation r de schéma R sont discernables : la valeur de la clé permet d’identifier de façon unique chaque élément de l’ensemble.
 +    * Au sein d'un schéma, il est souvent possible de définir plusieurs clés à partir des attributs. Le concepteur du modèle choisit une clé parmi les clés possibles. Cette clé est appelée **clé primaire**. 
 +    * Graphiquement, les attributs constituant la clé sont __soulignés__:
 +{{public:std-3:cm1:s7-cle-0.png}}
 +</note>
 +
 +<note>
 +**__Exemple 1__** :
 +
 +{{public:std-3:cm1:s7-cle-01.png}}
 +
 +</note>
 +
 +<note>
 +**__Exemple 2__** :
 +
 +{{public:std-3:cm1:s7-cle-02.png}}
 +
 +  *Pour certains schémas, 
 +    * il est courant de définir comme clé un entier **identifiant de façon unique** chaque élément de l'ensemble (appelé identifiant ou “Id”). 
 +    * La clé est alors constituée de cet attribut unique.
 +{{public:std-3:cm1:s7-cle-03.png}}
 +
 +**Représentation [[public:mco-2:paradigme_objet_et_modelisation_uml|UML]] **:
 +{{public:std-3:cm1:s7-cle-04.png}}
 +
 +</note>
 +
 +=== 6.3.2 Axiomes d'Amstrong ===
 +
 +Soit K une clé candidate. On démontre que KR à l'aide des //axiomes d'Amstrong// à partir d'un ensemble de DF connues:
 +
 +<note tip> **Axiomes d'Amstrong **
 +
 +  - **Réflexivité** : YXXY
 +  - **Augmentation** : XYX,ZY,Z
 +  - **Transitivité** : XY et YZXZ
 +  - **Pseudo-transitivité** : XY et Y,WZX,WZ
 +  - **Union** : XY et XZXY,Z
 +  - **Décomposition** : XY,ZXY et X>Z
 +</note>
 +
 +<note> ** Exercice **
 +
 +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?
 +</note>
 +====6.4 Normalisation d'un schéma====
 +__**Tables mal construites**__
 +<note>
 +** Exemple : fournisseurs de composants électroniques:**
 +
 +Fournisseur(nom_f, composant_,adresse_f, prix)
 +
 +  * **Problèmes :**
 +    * **Redondance** : l’adresse des fournisseurs est répétée plusieurs fois
 +    * **Inconsistance** : mauvaise mise à jour => adresses différentes pour un même fournisseur.
 +    * **Problème Insertion** : on ne peut pas insérer dans la table un fournisseur qui ne fournit rien
 +    * **Problème suppression** : si un fournisseur ne fournit plus rien, on perd son adresse
 +  * Solution?
 +
 +    * Couper la table en 2?
 +<note warning>
 +Fournisseurs(nom_f, adresse_f)
 +Catalogue(composant, prix)
 +</note>
 +--> Impossible de retrouver les prix pratiqués par les différents fournisseurs.
 +
 +
 +  * Nouveau Schéma :
 +<note tip> 
 +Fournisseurs(nom_f, adresse_f)
 +Catalogue(nom_f, composant, prix)
 +</note>
 +--> Il est possible de reconstruire la table initiale en effectuant une jointure entre ces 2 tables sur l’attribut ''nom_f''.
 +
 +
 +</note>
 +
 +<note>
 +**Exercice** : Les tables suivantes sont-elles bien ou mal construites?
 +
 +  * **Enseignement** (__id_enseignant__, nom_enseignant, __matière, id_élève__, nom_élève)
 +
 +  * **Arrêt** (__num_train__, horaire, __nom_gare__, ville)
 +
 +  * **Facture** (__id_client, article__, date, montant)
 +</note>
 +
 +==== 6.5 Formes Normales =====
 +**__Les Formes normales__**
 +  * Restreignent les dépendances admises dans un schéma relationnel
 +  * Permettent d’éviter la duplication de l’information au sein des relations
 +  * Définissent une méthode 
 +    * de **décomposition** d’un schéma relationnel redondant 
 +    * en plusieurs schémas //liés entre eux//:
 + 
 +=== 6.5.1 2ème forme normale (2FN) ===
 +<note important>
 +**Dépendance fonctionnelle élémentaire (DFE) **
 +  * Soit R un schéma relationnel 
 +  * Soit X un ensemble d’attributs ⊆ R
 +  * Soit A un attribut de R
 +  * Il existe une DFE entre X et A ssi :
 +    * XA
 +    * Il n’existe aucun sous-ensemble YX tel que YA
 +</note>
 +
 +<note important>
 +**2ème forme normale (2FN) **
 +
 +  * Un schéma R est en 2FN :
 +    * ssi la clé primaire de R est en DFE avec tous les autres attributs. 
 +    * Donc : il n’y a pas d’attributs qui ne dépendent que d’une partie de la clé.
 +</note>
 +
 +<note tip>
 +**Exemple :**
 +Fournisseur(nom_f,composant_,adresse_f,prix)
 +nom_fadresse_f
 +nom_f,composantprix
 +⇒ Pas 2FN!!
 +</note>
 +
 +=== 6.5.2 Normalisation 2FN ===
 +  * Lorsqu’un schéma relationnel n’est pas en deuxième forme normale, __il doit être **normalisé**__:
 +
 +<note>
 +**Normalisation 2FN** :
 +  * Pour obtenir un schéma 2FN:
 +    * on “//découpe//” la table selon les DFE trouvées entre les attributs de la clé et ceux qui ne sont pas dans la clé. 
 +  * La normalisation consiste:
 +    * à créer une nouvelle table pour chaque DFE ainsi trouvée. 
 +
 +  * Soit :
 +R(A1,...,Ai,...,An_,B1,...,Bj,...,Bm)
 +    * avec :
 +AiDFEBj
 +A1,...,Ai,...,AnDFEB1,...,Bj1,Bj+1...,Bm
 +  * Alors le schéma de table doit être modifié comme suit :
 +R1(A1,...,Ai,...,An_,B1,...,Bj1,Bj+1...,Bm)
 +R2(Ai_,Bj)
 +
 +<note important>**Attention**
 +
 +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).  
 +</note>
 +</note>
 +
 +<note tip>
 +**__Exemple__**
 +  * __Avant__:
 +Fournisseur(nom_f,composant_,adresse_f, prix)
 +nom_fadresse_f
 +nom_f, composantprix
 +  * __Après__:
 +Catalogue(nom_f,composant_,prix)
 +Fournisseur(nom_f_,adresse_f)
 +
 +<note>
 +**Remarque :** le schéma est maintenant constitué de deux tables. 
 +  * Les tables ont un attribut commun : //nom_f// (clé primaire de la table Fournisseur). 
 +  * La clé primaire de la table des Fournisseurs est  dupliquée dans la table des prix (appelée ici **Catalogue**). 
 +  * On dit que //nom_f// est une **clé étrangère** de la table des prix (l’attribut fait référence à la clé primaire d’une autre table, en l’occurrence la table des fournisseurs - voir [[public:STD-3:CM2:Conception de bases de données:3.1.1]]). 
 +</note>
 +</note>
 +
 +=== 6.5.3 3ème forme normale (3FN) ===
 +
 +<note important>
 +**Dépendance Fonctionnelle Directe (DFD) :**
 +
 +La dépendance fonctionnelle entre 2 attributs Ai et Aj est //directe// s’il n’existe pas de Ak tel que :
 +AiAkAj
 +</note>
 +
 +<note important>
 +**3ème Forme Normale (3FN)**
 +
 +Un schéma est 3FN :
 +  * S’il est 2FN
 +  * Si tous les attributs sont en DFD avec la clé.
 +</note>
 +
 +<note>
 +**Exemple :**
 +
 +Commande(num_commande_,nom_f, adresse_f, composant, quantité)
 +num_commandenom_f, composant, quantité
 +nom_fadresse_f
 +
 +Le schéma n’est pas 3FN!! (dépendance transitive entre num_commande et adresse)
 +</note>
 +
 +
 +=== 6.5.4 Normalisation 3FN ===
 +* Lorsqu’un schéma relationnel n’est pas en troisième forme normale, __il doit être **normalisé**__:
 +
 +<note>
 +**Normalisation 3FN**
 +  * On crée une table pour chaque DFD trouvée au sein des attributs n'appartenant pas à la clé. 
 +
 + 
 +Soit :
 +R(A1,...,Am_,B1,...,Bi,...,Bj,...,Bn)
 +avec : 
 +A1,...,AmDFDB1,...,Bi,...,Bj1,Bj+1,...,Bn
 +BiDFDBj
 +Alors :
 +R1(A1,...,Am_,B1,...,Bi,...,Bj1,Bj+1,...,Bn)
 +R2(Bi_,Bj)
 +
 +<note important>
 +** Attention **
 +
 +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.
 +</note> 
 +
 +</note>
 +
 +<note>**Exemple :**
 +
 +__Avant__ :
 +  * **Commande** (__num_commande__, nom_f, adresse_f, composant, quantité)
 +  * avec :
 +    * num_commande →  nom_f, composant, quantité
 +    * nom_f →  adresse_f
 +
 +__Après__ :
 +  * **Commande** (__num_commande__, nom_f, composant, quantité)
 +  * **Client** (__nom_f__, adresse_f)
 +
 +L’attribut nom_f est maintenant clé primaire de la table Client et clé étrangère de la table Commande.
 +</note>
 +