Bonsoir,
![Citation](https://forum.developpez.be/images/misc/quote_icon.png)
Envoyé par
CinePhil
Il n'y a donc que deux tables qui entrent en jeu, avec toutefois un léger bémol : cette requête donnera les commandes d'Albert sur lesquelles on peut effectuer une livraison à partir du magasin mais ne dit pas quels produits pourront être livrés et en quelle quantité.
Pour cet exemple, c’est vrai. Mais dans le cas général, il y a bien des requêtes pour lesquelles, du fait de l’identification relative, des tables intermédiaires ne sont pas concernées pour l’obtention des résultats. En l’occurrence, j’ai observé — depuis quelques années déjà — que DB2 dégraisse de lui-même les requêtes, pour ne retenir que les éléments de jointure nécessaires et suffisants (DB2 doit connaître Guillaume D’Ockham...)
![Citation](https://forum.developpez.be/images/misc/quote_icon.png)
Envoyé par
CinePhil
J'ai lu récemment, chez SQLPro je crois, que les clés primaires composées, jusqu'à deux voire trois colonnes ça va encore mais au delà ça craint (complexité au moins, performances peut-être ?)
Considérons le MCD suivant (repris d’une discussion avec wafiwafi) :
Et le MLD correspondant :
Vous parlez de complexité. Cela concerne-t-il la difficulté d’écriture des requêtes ?
Qu’on utilise l’identification absolue (clé mono-attribut) ou relative (clé multi-attributs), il faut considérer le nombre de jointures qui en théorie est le même dans les deux cas, ainsi que le nombre de AND connectant les attributs participant à chaque jointure (nombre égal au nombre - 1 d’attributs de la clé étrangère impliquée).
Dans le cas de SQL, le nombre de AND rend la tâche un peu plus pénible lors de la rédaction des requêtes, mais je ne vois pas là de complexité (pour la petite histoire, dans le contexte du Modèle Relationnel de Données le nombre de AND est égal à 0, voyez la description de la jointure dans l’article Bases de données relationnelles et normalisation, Annexe B).
Quant au nombre de jointures, en cas d’identification absolue il est irréductible, contrairement à ce qui peut se produire avec l’identification relative et ce de façon importante. Exemple :
Quels camions livreront le client Tartempion (de Siret 12345678901234) pour qui les livraisons ont le statut Y3
Dans le contexte de l’identification relative, on utilisera une requête mettant en jeu 3 tables :
1 2 3 4 5 6
| SELECT a.ClientNom, c.CamionImmat
FROM Client AS a
JOIN Livraison AS b ON a.ClientId = b.ClientId
JOIN Camion AS c ON b.CamionId = c.CamionId
WHERE a.ClientSiret = '12345678901234'
AND b.LivraisonStatut = 'Y3' ; |
Alors que si l’on ne met pas en œuvre l’identification relative, il faudra mettre en oeuvre l’ensemble des tables intermédiaires :
1 2 3 4 5 6 7 8 9
| SELECT a.ClientNom, f.CamionImmat
FROM Client AS a
JOIN Commande AS b ON a.ClientId = b.ClientId
JOIN LigneCommande AS c ON b.CommandeId = c.CommandeId
JOIN Engagement AS d ON c.LigneCommandeId = d.LigneCommandeId
JOIN Livraison AS e ON d.EngagementId = e.EngagementId
JOIN Camion AS f ON e.CamionId = f.CamionId ;
WHERE a.ClientSiret = '12345678901234'
AND e.LivraisonStatut = 'Y3' ; |
Concernant la performance :
En examinant cette requête, non seulement le nombre de tables supplémentaires en jeu est la cause d’une inflation des lectures physiques, mais le nombre de celles-ci est malheureusement encore démultiplié par le fait que les lignes à lire sont nécessairement dispersées dans les enregistrements physiques « sur le disque ». Au contraire, si ces lignes sont regroupées dans les enregistrements, « effet cluster » rendu possible grâce à l’attribut « générique » ClientId, le nombre de lectures sera minimal. Pour l’avoir observé au gnagnascope (par exemple avec l’outil Detector) dans l’environnement DB2 for z/OS (univers des mainframes), je parle en connaissance de cause des bienfaits qu’on en retire. Ce genre de requêtes, pour traiter d’un client ça n’est pas sensible, pour deux clients ça va toujours, mais à l’échelle cent mille, vous m’en direz des nouvelles. Vous serez dramatiquement « I/O Bound » (la CPU se tourne les pouces, elle attend que les lectures soient achevées pour passer à la suite des opérations).
En complément :
Grâce à l’identification relative, au niveau physique, on fera des économies d’index, puisque l’index primaire, par exemple celui de la table Engagement, contient à la fois les valeurs de la clé primaire et celles de la clé étrangère en relation avec la table LigneCommande. Et bien entendu, qui dit accès physique à une valeur de la clé primaire de la table Engagement dit récupération de facto de la valeur de la clé étrangère référençant la table LigneCommande, puisque la 1ère contient la 2e. Il en résulte un gain supplémentaire en performance (notamment en cas de jointure, réputée coûteuse selon une légende tenace, entretenue par ceux qui n’en ont jamais scruté le comportement au gnagnascope).
![Citation](https://forum.developpez.be/images/misc/quote_icon.png)
Envoyé par
CinePhil
L'identification relative fera que :
- La clé primaire de la table Commande aura 2 colonnes (ClientId, CommandeId).
- Celle de la table LigneCommande en aura trois (ClientId, CommandeId, LigneCommandeId).
- Celle de la table EngagementLigneCommande en aura 4 (ClientId, CommandeId, LigneCommandeId, EngagementLigneCommandeId).
On pourrait donc opposer qu’une clé primaire comme celle de la table Livraison consomme de la place. En réalité (au moins avec DB2 for z/OS), si vous comptez 4 octets pour l’attribut ClientId, puis deux octets pour chaque attribut relatif, la clé primaire de la table Livraison requerra 12 octets, ce qui n’est pas la mer à boire, d’autant plus que sur ces 12 octets, 10 d’entre eux correspondent à la clé étrangère : en identifiant de façon absolue, on compterait 8 octets, à savoir 4 pour la clé primaire, plus 4 octets pour la clé étrangère, ce qui ferait en tout un gain minime de 12 - 8 = 4 octets. Pas de quoi fouetter un chat...
Partager