Conseil bdd

Conseil bdd - SQL/NoSQL - Programmation

Marsh Posté le 28-11-2007 à 15:44:04    

Bonjour a tous,
 
j'ai juste une petite question qui me turlupine un peu.
 
je suis entrain de consevoir une base de donnees. j'ai une table 'publications'. pour une publication il peut y avoir plusieurs auteurs. j'ai par ailleurs une table 'auteurs' qui contient tous les auteurs.
 
j'ai eu l'idee de cree un seul champ 'auteur' ds la table 'publications' qui aura comme valeur: 'id_auteur1~id_auteur2~...'
 
comme le nombre d'auteur peut aller jusqu'a 8, j'ai pas voulu creer 8 champs : auteur1, auteur2,....
 
l'autre possibilite est de creer une autre table qui prendra l'identifiant de l'article et autant d'enregistrement que d'auteurs...
 
que feriez vous et que me conseillez vous?
 
merci par avance,
Reda

Reply

Marsh Posté le 28-11-2007 à 15:44:04   

Reply

Marsh Posté le 28-11-2007 à 15:50:19    

2 eme solution sans hesiter!

Reply

Marsh Posté le 28-11-2007 à 15:54:37    

Table de jointure, toujours. Tu ne devrais même pas te poser la question ;).
 
PS : ET JE T'INTERDIT DE CREER UN CHAMP ID AUTOINCREMENT DANS CETTE TABLE, TA PK SERA UNE CLE COMPOSEE CONSTITUEE DE (auteur_id, publication_id)


Message édité par MagicBuzz le 28-11-2007 à 15:55:00
Reply

Marsh Posté le 28-11-2007 à 16:12:59    

mers les gars pour vors reponses rapides :)
 
donc, je dois creer un autre table auteur où il y aura les identifiants des auteurs... ???
 
j'ai apeu pres 4 champs de ce type : auteur, source, mots cles, ... devrais alors creer une table pour les 4 champs??? ca ne fera pas bp de tables?
 
et pourquoi l'idee de les separer ne vous convient pas?
 
quel type devrais je attribuer au champs qui contiendra les identifiants : INT OU TINYINT ??
 
merci encore une fois

Reply

Marsh Posté le 28-11-2007 à 16:32:46    

non.
 
t'as une table "ecrit" avec deux champs (auteur_id, publication_id) qui sont une clé primaire composite.
il sont chacun des clés étrangères vers auteur.id et publication.id et sont de facto de même type.
 
les listes de valeur, c'est mal parceque tu ne pourras pas faire de jointure avec la table de référence, pas plus que tu pourras vérifier l'intégrité de cette dernière.
 
et oui, tu auras 1 table de ce type par relations de ce genre.

Reply

Marsh Posté le 28-11-2007 à 16:34:06    

MAgicBuzz, j'ai pas bien compris ton PS: je ne devrais pas creer un autoincrement ds quelle table???

Reply

Marsh Posté le 28-11-2007 à 16:42:47    

la table de jointure pardi :o

Reply

Marsh Posté le 28-11-2007 à 16:48:08    

OK, et sinon que pensez vous de ca:
 
table 'articles':
 
id     titre    resume
--------------------
1      t1         r1
2      t2         r2    
 
table 'article_infos':
 
id     type      id_article    id
------------------------------
1       a             1         1002
2       a             1         1006
3       s             1         1008
4       s             1         1002
5       m            1         1106
6       m            1         1178
7       m            1         1112
 
 
dans cet exemple l'article numero 1 a 2 auteurs, 2 sources et 3 mots cles
 
a noter que j'ai par ailleurs une 3 tables: 'auteurs', 'sources' et 'mots_cles'

Reply

Marsh Posté le 28-11-2007 à 17:18:45    

1/ vire le premier "id", il est inutile (c'est le truc que je t'ai formellement interdit de faire :D). la clé composite type, id_article, id est nécessaire et suffisante.
2/ la structure est effectivement intéressante. c'est utilisé sur l'erp avec lequel je travaille.
ça a des avantages et des inconvénients.  
les avantages :
- c'est que c'est assez facile à requêter, puisque t'as qu'un nom de table à garder en mémoire
- c'est aisément extensible sans devoir modifier le modèle
les inconvénients :
- niveau performances, c'est légèrement inférieur à des tables spécialisées
- il est impossible de gérer l'intégrité avec des foreign key (ça existe pas les fk conditionnelles)

Reply

Marsh Posté le 28-11-2007 à 17:29:40    

Oui, effectivement, le 1er id est a virer, c juste par erreur que je l'ai mis!! :D
 
bon, tu me poses une vrai colle là, je ne sais quoi utiliser: la solution que je viens de proposer ou des tables specialisees, les avantages et inconvenients me mettent ds l'impossibilite de prendre une decision :D que me co,nseilles tu??? :)
 
pour ton info, il y a plus de 80 000 articles
environ 3000 mots cles et 4000 sources...
 
 
j'ai oublie de dire que j'ai un autre champ 'langue' qui peut contenir plusieurs langues: en, fr, es, it. là aussi je dois mettre une table dediee a ca ou je peux les mettre ds le meme champ avec une separtion??
 
 
pour les identifiant, dois je utiliser les champs du type INT ou TINYINT?? quelle est la dif entre les 2??
 
 
merci merci merci mille fois :)

Reply

Marsh Posté le 28-11-2007 à 17:29:40   

Reply

Marsh Posté le 28-11-2007 à 17:35:36    

pour la gestion de la langue, je te conseille, ce sera plus simple, de faire deux articles, un en français, un en anglais (donc deux lignes, et un champ "langue" ) dans la table des articles.
 
et les mots-clés, par exemple, devraient être localisables, donc tu rajoute la langue dans la table dédiée à la correspondance article/motclé, et tu fais pareil dans la table des mots-clés que dans latable articles.
 
évidement, les clés de article et motclés deviennent le couple (langue, id)
 
ensuite, pour ce qui est du choix entre tables dédiées ou table fourre-tout, j'ai pas de réponse universelle à donner.
le plus propre, c'est les tables dédiées, mais pour diverses raison la fourre-tout peut être plus intéressante...


Message édité par MagicBuzz le 28-11-2007 à 17:36:32
Reply

Marsh Posté le 28-11-2007 à 17:49:56    

au fait pour la langue, l'article en lui meme peut etre en 2 ou 3 langues, ce ne sont pas des articles separes!! que devrais je faire alors?
 
3 petites dernieres question et je te laisse en paix ;)
 
je connais les identifiants des articles que je veux selectionner:
10032
12254
75586
...
21358
 
disant j'ai une centaine stoquees dans une variable de type tableau.
 
est il mieux faire un SELECT * FROM articles WHERE (id = '10032' OR id = '12254' OR id = '75586' ...)
 
ou bien de faire des select imbriques:
foreach(ma_variable as $id)
{
 SELECT * FROM article WHERE id = '$id'
}
 
2eme question :) :
pour les identifiant, dois je utiliser les champs du type INT ou TINYINT??
 
3eme et derniere question, je te la poserai tt a l'heure pour que ca fasse pas trop... ;)
 
merci

Reply

Marsh Posté le 29-11-2007 à 13:51:39    

aucune reponse???!! :(

Reply

Marsh Posté le 29-11-2007 à 22:45:38    

Même si "IN" est une statement à éviter, il sera très clairement infiniment plus performant que de lancer une série de requêtes.
 
En effet, pour ce genre de requêtes, ton programme et le SGBD vont passer plus de temps à vérifier la syntaxe, calculer le plan d'exécution, et convertir les données retournées qu'à faire la requête elle même.
 
Pour schématiser, avec des valeurs bidons :
 
IN = 1 ms par clause
Transfert d'une requête à travers le réseau : 1 ms
Analyse syntaxique d'une requête : 1 ms
Mise en place du plan d'exécution : 1 ms
Exécution de la requête : 1 ms
Lecure des données sur le disque : 1 ms par ligne
Transfert des données sur le réseau : 1 ms par ligne
Conversion des données dans les types du langage client : 1 ms par ligne
 
Donc dans le cas d'une requête avec un IN qui porte sur 100 éléments :
 
IN = 1 ms par clause * 1000 = 1000 ms
Transfert d'une requête à travers le réseau : 1 ms
Analyse syntaxique d'une requête : 1 ms
Mise en place du plan d'exécution : 1 ms
Exécution de la requête : 1 ms
Lecure des données sur le disque : 1 ms par ligne * 1000 = 1000 ms
Transfert des données sur le réseau : 1 ms par ligne * 1000 = 1000 ms
Conversion des données dans les types du langage client : 1 ms par ligne * 1000 ms
--------------------
1000 + 1 + 1 + 1 + 1 + 1000 + 1000 + 1000 = 4005 ms
 
Et dans le cas de 1000 requêtes exécutées :
 
IN = 1 ms par clause * 0 = 0 ms
Transfert d'une requête à travers le réseau : 1 ms * 1000 ms = 1000 ms
Analyse syntaxique d'une requête : 1 ms * 1000 ms = 1000 ms
Mise en place du plan d'exécution : 1 ms * 1000 ms = 1000 ms
Exécution de la requête : 1 ms * 1000 ms = 1000 ms
Lecure des données sur le disque : 1 ms par ligne * 1000 = 1000 ms
Transfert des données sur le réseau : 1 ms par ligne * 1000 = 1000 ms
Conversion des données dans les types du langage client : 1 ms par ligne * 1000 ms
--------------------
0 + 1000 + 1000 + 1000 + 1000 + 1000 + 1000 + 1000 = 7005 ms
 
En gros, on se pose meme pas la question ;)
 
Et en réalité, c'est bien pire que ça, on frôle le rapport de 1/nblignes ;)

Reply

Marsh Posté le 30-11-2007 à 10:52:05    

merci pour ces explications detaillees :)
 
OK, je dois donc utiliser SELECT * FROM table WHERE id in ('10032','12254', '75586' ...)
 
cool, merci bp ;)

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed