difficulté conception base de données

Eléphanteau du PHP | 29 Messages

19 oct. 2008, 19:34

Bonsoir,
Je suis en pleine réflexion pour la construction de ma base de données (table,champ...)

Je vous expose mon projet:

Mon projet doit permettre a mes visiteurs inscrit de pouvoir visualisé un nombre de vidéo restreint par jour et par catégorie, chaque visiteur a la possiblité ensuite, de s'acheter des crédits pour consulté plus de vidéo (ex: catégorie 1: 5 video par jour, un achat de crédit lui donnerait 10 vidéo supplémentaire)

Je souhaite également conservé pendant un certain temp une sauvegarde des vidéos regardé par les membres, avec le pseudo, la vidéo ainsi que l'heure.

Pour le ciblage publicitaire, je souhaite également préparé ma base afin de pouvoir segmenter les profils de mes membres.

J'ai commencer par faire une table membre:

Code : Tout sélectionner

-Nom -Prenom -Date de naissance -adresse -code postal -ville -pays
ensuite une table compte

Code : Tout sélectionner

-Pseudo -Pass -nombre de visite -Derniére connection
Dans mon premier site que j'avais fait j'avais sa:

table générale:
-pseudo
-pass
-prenom
-nom
-adresse
-ville
-cp
-pays
-nombre de visite
-derniére connection
-nb_video_cat1 (par defaut 5)
-nb_video_cat1_acheter
-nb_video_cat2 (par defaut 5)
-nb_video_cat2_acheter
-nb_video_cat3 (par defaut 5)
-nb_video_cat3_acheter
(ainsi de suite suivant le nombre de catégorie)
-préférence1 (choix oui/non)
-préférence2 (choix oui/non)
-préférence3 (choix oui/non)
(ainsi de suite suivant le nombre de préférence)
Pour les sauvegardes j'ai créer une table pour chaque catégorie, et a chaque visionnage je faisait un enregistrement avec le pseudo, la video et l'heure.

Vous aurez donc comprit que j'avais fait au plus simple sans vraiment me posé de question :s, sa fonctionné, mais ce n'était certainement pas optimiser, de plus j'ai eu beaucoup de difficulté a transférer mes tables lorsque j'ai changé de serveur.
Le site avait une base d'environt 60 000 membres.

J'avoue etre un peu perdu afin d'optimiser tout sa :s, en plus je souhaite maintenant garer des infos sur les catégorie des vidéo(combien de visionnage a eu la catégorie...)
La je bloque sur la facon de faire pour limiter le visionnage par catégorie (sans faire tout a la suite comme auparavant, qui n'était pas je pense optimisé), puis égalemet la gestion d'achat de crédit (il me faut obligatoirement un champ a part, car les vidéos acheté sont débité uniquement si les video quotidienne ont été vu, et donc si sa se chevauche sur 2 jours, le membres retrouve 5 videos gratuites avant de piocher dans ces crédits.

J'espere que vous pourrez m'aidez car j'avoue que la je suis bien embetter :s

Merci d'avance pour votre aide:)

Eléphant du PHP | 254 Messages

19 oct. 2008, 21:10

Salut :)

Alors tes tables membre et compte pourraient etre une seule table mais tu as besoin de les fractionner en deux. Dans ce cas il faudrait avoir un dénominateur commun pour les relier, savoir quel membre correspond a quel compte

Sinon ensuite pour tes vidéos il te faut une table catégorie, une table vidéo, avec un champ id-catégorie dedans si une vidéo a une seule catégorie. Si une vidéo peut appartenir a plusieurs catégorie il te faut une table pour décrire la relation, genre :

VIDEOCAT
id_video
id_cat

Ensuite il te faut de quoi relier les vidéos aux membres/comptes, donc une table de relation :

VISIONNAGE
id_membre
id_video
date_visio

Pour savoir si tel compte a atteind son cota de visoonnage pour la journée, il te suffit de compter les enregistrement de la table VISONNAGE correspondant a la date du jour

Code : Tout sélectionner

SELECT COUNT(*) FROM visonnage WHERE date_visio=NOW();

Eléphanteau du PHP | 29 Messages

19 oct. 2008, 23:47

Re-bonsoir,
Merci de ta contribution furiouslol :)

Je n'avais pas pensé a ta solution de compter le nombre d'entré dans la table pour vérifier le quota, mais j'ai peur que se ne soit pas possible, car je laisse la possibilité au membre d'acheter des visionnage supplémentaire, et cela ne sont débité que si les visionnages du jour sont a 0

Ces pourquoi je me dirigez vers quelque chose comme sa:

Code : Tout sélectionner

PARAM_VISION id_membre nb_cat1_quotidienne (initialisation a 5 tout les jour a 00h) nb_cat1_supplémentaire nb_cat2_quotidienne (initialisation a 5 tout les jour a 00h) nb_cat2_supplémentaire nb_cat3_quotidienne (initialisation a 5 tout les jour a 00h) nb_cat3_supplémentaire ... (jusqu'au nombre de catégorie disponible environ 20)
Chaque video n'appartient qu'a une catégorie.Lorsque une video de la catégorie 1 (par exemple) est visionner, je décremente de 1 nb_cat1_quotidienne, une fois a 0, je décremente nb_cat1_supplémentaire si c'est supérieur a 0, sinon l'accés au video est fermé jusqu'au lendemain.

Mais du coup en utilisant cette technique (peut etre que sa ne change rien d'ailleur par rapport a mon premier site ou tout était dans une table), a chaque inscription d'un membre, j'ajoute une entré dans ma table "MEMBRE" (qui peut contenir membre et compte, mais je ne sait si pour l'optimisation il vallait mieux séparé ou pas), puis j'ajoute une entré dans ma table "PARAM_VISION", puis dans la meme logique je ferait la meme chose avec les préférences de mes membres dans une table "PREF_MEMBRE"

Mais en me basant sur mon ancienne expérience (base de 60 000 membres environ) et celle des concurrents identifier (entre 600 000 et plus de 1 000 000 de membre pour certain),
faire pour une inscription, 3 enregistrements dans 3 tables est correct ou pas?? (j'avoue que je ne sait pas trop...)
Car rien que en me basant sur mon ancienne expérience, sa ferait 3 tables avec 60 000 entrés, et pour les concurrents, 3 tables de 600 000 entrés, je suis pas sur que sa soit correct :s

J'espere que vous pourrez me renseigner, si vous avez besoin d'autre info pour mieux comprendre mon probléme (si je ne suis pas assez précis) n'hésitez pas a demander :)

Merci beaucoup de votre aide :), si vous avez des liens avec des exemple de structure je veut bien aussi :)

Eléphant du PHP | 254 Messages

20 oct. 2008, 01:07

Je n'avais pas pensé a ta solution de compter le nombre d'entré dans la table pour vérifier le quota, mais j'ai peur que se ne soit pas possible, car je laisse la possibilité au membre d'acheter des visionnage supplémentaire, et cela ne sont débité que si les visionnages du jour sont a 0
Rien n'empeche

En fait simplement a ce sujet je propose de n'avoir qu'un conceptuel de donnée minimaliste et relationnel, que tu comptes tes enregistrements dans ton programme php ou que tu décrémente une valeur par défaut reviens au meme au final, pour rajouter ta clause de visionnage supplémentaire il faut rajouter des choses a ce que je propose ...

A ce sujet je ne vois pas trop ton besoin, combien de visionnage supplémentaire, ou a quelle condition .... Ta table PARAM_VISION laisse suggérer que tu accorde X visionnage supplémentaire par catégorie de vidéo ? En tout cas ta facon de créer cette table me semble bizarre; j'ai plus l'habitude de gérer les données indépendament ...

Genre dans ton exemple, ajouter une catégorie de vidéo t'oblige a mettre a jour ta table PARAM_VISON, en lui rajoutant 2 lignes par catégorie ajoutée, j'avoue je vois mal l'interet, ou alors j'ai pas compris :lol:
Et a chaque fois que tu ajoutes un membre dans ta BDD, c'est pire, ca t'oblige a ajouter dans le meme temps 40 ligne a cette meme table (si on part du principe que tu as 20 catégories)
Mais encore une fois je t'ai peut etre mal compris :)

Eléphanteau du PHP | 29 Messages

20 oct. 2008, 01:49

Non tu as bien comprit :)

Pour les visionnages supplémentaire mon visiteur choisira pour quel catégorie ils veut des "crédits", et un paiement lui donne x (environ 10) crédit, ces pourquoi j'avais pensé a faire 2 champ pour 1 catégorie.
Aprés il y a certainement moyen de faire beaucoup mieux, et plus logique/optimisé, c'est pour sa que je viens vous demandez conseils :)

Sur mon précédent site, j'avais si on veut presque que 1 grosse table ou toute les informations que j'ai noté plus haut etait réunis (toutes les infos perso, info du compte, le nombre de visionnage quotidien(1 par catégorie), le nombre de visionnage acheté(1 par catégorie) ), sa fesait une table avec beaucoup de champ, et elle contenait environ 60 000 entrés.

Voila, j'espere avoir réussi a éclairé un peu plus mon projet, et je vous remerci de votre aide :)

P.S: je suppose donc que la facon de faire que j'ai pensé dans mon message précédent n'est pas bonne :)

Eléphant du PHP | 254 Messages

20 oct. 2008, 10:19

Ok donc il te faut acquérir les notions basiques en base de donnée relationnelle, et faire tout ton conceptuel de base de donnée avec. Je suis pas tres bon en théorie, j'ai appris sur le tas et j'ai encore pas mal de chose a apprendre, aussi je ne suis pas le mieux placé pour te faire un descriptif de la méthode, mais deja il te faut séparer tes donnée de facon a ce qu'elles soient indépendantes.

Ensuite dans ton exemple PARAM_VISION, tu stockes en base de donnée des valeurs qui pourraient s'obtenir dans ton programme avec quelques requetes simples et bien senties, comme les exemple que je t'ai précédement donné. Cette table est a mon sens a éviter, pour les raisons précédement citées.

Une table vidéo, une table catégorie, une table membre, une table qui fait la relation entre membre et video

Ensuite pour ton soucis de différenciation entre les vidéo visionnées gratuitement et celle qui sont payantes, tu peux séparer ta table de relation membre/video en deux(une qui stocke les gratuites et une pour les payantes), soit, ce qui est encore plus efficace, avoir un flag dans cette table qui vaut 0 ou 1 (visionnée gratos ou payée)

Tes controles pour savoir si il doit payer ou pas la vidéo qu'il veut regarder se fait en fonction du nombre de vidéo qu'il a déja regardé dans la journée, ces controles tu peux les faire dans ton programme facilement

Eléphanteau du PHP | 29 Messages

21 oct. 2008, 20:47

Re-bonjour,
Merci de tes infos :)
Je vais me penché sur la structure a adopté.

J'avais également pensé a faire une table par catégorie, et a chaque enregistrement d'un membre, il s'enregistre en meme temp dans les catégorie.
Mais du coup si il y a 10 000 membres, il y a également 10 000 enregistrement dans chaque table catégorie.

Si d'autre personne on également des avis, surtout n'hésitez pas a les partagers :)

Eléphant du PHP | 254 Messages

21 oct. 2008, 21:43

Non non :)
c'est justement la le soucis dnas ta compréhension du systeme de donnée, si tu créé une table catégorie, elle doit etre de cette forme la :

Code : Tout sélectionner

CATEGORIE id_catégorie (clé primaire autoà incrémentable pâr exemple) nom (de la catégorie)
Ca suffit amplement pour la table catégorie, pas d'id membre dans cette table, d'ailelurs c'est une table de catégorie de vidéo.

Ta table video:

Code : Tout sélectionner

VIDEO id_video (clé primaire autoà incrémentable pâr exemple) nom (titre) de la video) ici tu rajoute les renseignements propres a ta vidéo, exemple le réalisateur, la durée etc ... pas d'id_membre !!
Ensuite il te faut te poser la question suivante: une video peut elle appartenir a une ou a plusieurs catégorie ? Si chaque vidéo appartient a une et une seule catégorie de vidéo, alors tu peux rajouter un champ id_catégorie dans ta table VIDEO
Sinon il te faut une troisieme table qui stockera ls relations entre vidéo et catégorie :

Code : Tout sélectionner

VIDEOCAT id_video id_categorie
Il te reste a traiter la relation entre tes membres et tes videos. Chacun de tes membres va visionner une ou plusieurs videos (voire meme aucune). Pas de soucis, tu créé une table relationnelle pour stocker ca

Code : Tout sélectionner

VISIONNAGE id_membre id_video date_visio
En stockant ca, tu sais exactement qui a regardé quoi et a quel moment, tu peux donc facilement savoir qui a visonné combien de vidéo a quelle date, ce qui est déja pas mal pour ton probleme

Il te reste plus qu'a distinguer les visonnages payant de ceux qui sont gratuits. Pour ca il te suffit de rajouter un champ "gratos" dans ta table VISONNAGE, qui contiendra 0 ou 1 selon les cas. Ta table devient donc

Code : Tout sélectionner

VISIONNAGE id_membre id_video date_visio gratos (exemple 0 pour gratuite et 1 pour payante)
Ainsi pour savoir si untel a atteind son quota de vidéos gratuite pour la journée, une petite requete suffira :

Code : Tout sélectionner

SELECT COUNT(*) FROM VISIONNAGE WHERE id_membre="id de untel" AND date_visio=NOW() AND gratos=0;
Si le résultat de cette requete est 5, alors le type n'a plus de credit gratos pour la journée, tu lui refuse le visionnage gratos, sinon c'est ok il peut regarder gratos

Voila de cette facon tu as des tables efficaces, qui ne gonfleront pas exessivement. La seule table qui gonflera avec le temps sera la table VISONNAGE, puisqu'elle prendra une ligne a chaque fois qu'un membre regardera une vidéo, mais on est loin de ta table PARAM_VISION tout de meme ...
Apres je ne sais pas quel est ton niveau en SQL, car il va falloir faire des requetes pour pouvoir lire tout ca et l'utiliser dans ton application, mais tu me demandes comment optimiser, je te répond "fait comme ca, ca te formera et tu verras ca te plaira" :)

PS: a ce sujet y a un tres bon tuto sur les JOINTURE sur ce forum si jamais t'as besoin

Eléphanteau du PHP | 29 Messages

21 oct. 2008, 22:47

Merci beaucoup de toutes tes explications et du temp que tu me consacre.
Je vais regarder avec beaucoup d'interet ta solution.

J'ai déja une question quand meme par rapport a la table visionnage.
Si je propose a chaque visiteur 5 vidéos gratuite par jour, sa fait 5 entré par visiteur, donc en partant du principe que sa va marcher (il faut quand meme etre optimiste), et en imaginons (ce que j'espere bien sur, pas au début ces sur mais bon) qu'il y est 10 000 visiteurs par jour (ce chiffres est en dessous des concurrents identifié), sa fait 50 000 entrés dans la table. les traitement dessus, le comptage a proprement parler d'entré pour un membre se fera t'il facilement, ou le traitement sera compliqué?

Je te remercie en tout qu'a pour toute ton aide :)

Eléphant du PHP | 254 Messages

22 oct. 2008, 01:31

Oué c'est la question a se poser, c'est la seule table qui va gonfler, cependant elle sera capable de le faire car d'une structure tres simple, les deux id qui la compose etant des entiers.

On a donc une table d'une structure tres réduite, qui risque de prendre du poid néanmoins assez rapidement si tu as du gros traffic, la on peut causer réellement d'optimisation, je ne pense pas que le COUNT pose beaucoup de probleme mais je connais mal les limites mysql pour te répondre, aussi je vais laisser la parole aux anciens qui m'ont laissé causer jusque la :)

Alors la question est :

Y a t'il un autre conceptuel plus adapté a une table qui recoit beaucoup d'update, et sinon quels systemes mettre en place pour maitriser la taille de cette table ?

Eléphanteau du PHP | 29 Messages

23 oct. 2008, 17:34

Merci a toi furiouslol pour toute ton aide, par contre mon sujet n'a pas l'air spécialement attractif pour d'autre avis/explication :s
Je vais essayé d'apprendre la logique de conception d'une bdd, sa m'aidera surement, malgré qu'au premier abord sa ne semble pas spécialement simple.

Si d'autre lecteurs on des avis par rapport aux questions ci-dessus, n'hesitez pas a laissé votre analyse/idée, je prend tout :)

Encore merci a toi furiouslol :)

Eléphant du PHP | 254 Messages

24 oct. 2008, 00:45

Ouais je pensais que ca allait réagir la dessus :) Je t'ai exposé les bases a mon sens, le tout etant d'essayer d'éviter la redondance d'information, par contre en terme de limite d'utilisation j'aurias aimé avoir aussi un avis

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

24 oct. 2008, 10:38

Bonjour,
Ce n'est pas parce qu'il n'y a pas d'interventions que le sujet n'est pas attractif. Mais, mine de rien, il y a des gens qui suivent en silence car ils écoutent ce que vous dites d'autant plus que ce que te propose furiouslol est juste.

La question du poids d'une table dans une base de données est crucial non seulement pour les traitements appliqués à cette table mais aussi pour sa maintenance : backup, import/export , ... surtout pour MySQL.

L'optimisation du volume est une question mathématique à laquelle la méthode conceptuelle relationnelle apporte quelques solutions surtout au niveau de la structure et du formatage des données à enregistrer dans une table.

Voici un exemple simple:
Si on doit conserver les données d'identité des membres, il faut une table "membre" dont les champs représentent l'ensemble des données à collecter sur un membre.
Ex minimaliste: Membre (id, nom, prenom, email)
Le volume de données de cette table dépend considérablement des types et de la taille binaire (octet) de ses champs.
Donc, si le format est le suivant :

Code : Tout sélectionner

Membre (id int, nom varchar(15), prenom varchar(15), email varchar(50))
La longueur d'un enregistrement en octet =
  • id (4 oct)
    + nom (15 oct)
    + prenom (15 oct)
    + email (50 oct)
    ------------------------
    = 84 oct.
Le volume de cette table pour une charge de 10 000 enregistrements = 84 oct x 10 000 = 821 Ko

Avec cette formule de calcul, on constate que si le nombre de champs change(augmente ou diminue), le volume change (augmente ou diminue respectivement) alors systématiquement pour un même nombre d'enregistrements.
De même, si les formats (type/taille) de données changent, le volume change aussi pour un même nombre d'enregistrements.
Et finalement le volume peut changer aussi si le nombre d'enregistrements change.

On comprend par ça que le volume en octets dépend fortement de 3 événements : le nombre de champs, le format de données choisi pour les champs et le nombre d'enregistrements stockés dans la table.
La question de l'optimisation du volume doit être projetée donc sur ces trois axes.

Mais on peut remarquer que les deux axes concernant les champs (nombre et format) ont un caractère prépondérant par rapport à l'axe concernant le nombre d'enregistrements. Car il faut bien fixer la structure de la table avant de la mettre en service pour accueillir les données.
C'est pour cela que l'optimisation de la structure ou format des données est une question qu'il faut aborder au niveau de la structuration et la création de la base de données et non à postériori.

Par contre, l'optimisation au niveau du nombre d'enregistrements d'une table peut avoir des solutions relevant de l'administration de données comme l'archivage et l'épuration, le découpage logique et le clusturing ...

En ce qui te concerne, je te conseille, puisque tu es en train de restructurer ta base, de bien réfléchir sur le découpage des structures de tes tables, la distribution des champs et leur formatage (type/taille) sans rentrer en conflit avec le format et le contenu des données existantes.

Le découpage et la mise en relation des tables engendre un dédoublement de données liées ; pour ne pas affecter trop le volume global de la base il est conseillé d'utiliser des index numériques (clés primaires, clés étrangères, index de regroupement et index de contrainte d'unicité) comme liens entre les tables (selon le modèle relationnel)
Le choix du format du champ (type/taille) jouant le rôle d'index est important car un index engendre un dédoublement des enregistrements concernant ce champ. C'est pour cela qu'un format numérique (le plus petit possible => entier) est souvent recommandé.

En ce qui concerne les limites d'une base de données MySQL, je pense que c'est une question qui est relative à la configuration de l'environnement dans lequel MySQL tourne (les outils déployés pour l'administrer, le client qui l'interroge par des requêtes, etc...)

Par exemple, Si c'est un environnement Web utilisant PHP, le premier événement qui risque de perturber et le timeout Web qui pourrait ne pas convenir avec le temps d'attente de la réponse du serveur de données suite à une requête sur une table trop lourde ou à une requête complexe (trop de champs, de relations...)
Deuxième exemple, si on utilise Un utilitaire Web pour administrer MySQL comme PHPMyAdmin, le premier événement qui perturbe est la configuration du débit autorisé pour le postage ou l'upload de données lors d'import/export ou de chargement de script SQL.
Le troisième exemple concerne le problème relatif aux données de type texte : l'encodage des caractères et les délimiteurs et le problème des caractères binaires comme le contenu d'une image incorporée.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Eléphant du PHP | 254 Messages

24 oct. 2008, 11:55

Merci sadeq :)

C'est vrai rif15 que les prévisions de fréquentation de ta base de donnée sont assez importantes, et donc le format de chaque champs doit etre soigneusement étudié, l'efficacité de ta base en dépend a terme

Ensuite pour revenir au options d'archivage, pour ta table VIDEOCAT décrivant qui a regardé quoi et quel jour, il te faut définir quels besoins cette table doit remplir dans le temps. Pour ton traitement de savoir si un user peut regarder une vidéo gratuitement ou non tu n'as besoin que des enregistrement du jour, par contre, vu que tu traite des données clientes, tu es un peu obligé de garder un historique des visionnages pour diverses raisons auquelles tu dois réfléchir.

J'ai eu une fois a faire a un archivage de donnée, celui ci etait effectué par un cron sous unix, qui lancait un script tous les jours a telle heure, s'occupant de delester la table en question et d'en remplir une autre, pour des besoins statistiques, c'est une solution.

Eléphanteau du PHP | 29 Messages

24 oct. 2008, 20:04

Ce n'est pas parce qu'il n'y a pas d'interventions que le sujet n'est pas attractif. Mais, mine de rien, il y a des gens qui suivent en silence car ils écoutent ce que vous dites d'autant plus que ce que te propose furiouslol est juste.
Je suis tout a fait d'accord :) et je comprend tout a fait que tout le monde ne réponde pas, mais certain continue a suivre un sujet qui les intéresses :)

Comme tu la bien fait remarqué furiouslol a bien expliqué des solutions a la problématique, et je te remercie de ta contribution également :)