8795 sujets

Développement web côté serveur, CMS

Bonjour,

Je souhaite créer une base de données de films un peu kitsh pour un projet de VOD que je dois effectuer lors d'un projet d'école.

J'ai donc 5 bases distinctes :

- serial_films : base de films avec toutes les informations associées (description, acteurs etc.)

- serial_origines : base d'intitulé d'origine des films (américain, français etc.)
- serial_films_l_origines : base qui relie les id des films aux id des origines sachant qu'un film peut avoir plusieurs origines donc plusieurs rows par films

- serial_genres : base d'intitulé des genres de films (action, aventure etc.)
- serial_films_l_genres : base qui relie les id des films aux id des genres sachant qu'un film peut avoir plusieurs genres

Mon but est de créer en une seule requête un tableau de résultat comprenant toutes les informations sur un film dont ses origines et ses genres associés. J'ai donc utilisé un GROUP CONCAT pour mettre en une row et séparés par des virgules associées les genres associés au film, jusque là tout est OK. Voici la requête :

SELECT id, titre, jaquette, description, realisateur, acteurs, duree, annee, GROUP_CONCAT( intitule_genre SEPARATOR ', ' ) AS genre
FROM serial_films, serial_films_l_genres, serial_genres
WHERE serial_films.id = serial_films_l_genres.id_film
AND serial_films_l_genres.id_genre = serial_genres.id_genre_p
GROUP BY id
LIMIT 0,120


Elle marche parfaitement mais voilà, j'aimerai maintenant pouvoir ajouter à ce tableau de résultat, les origines associées donc si on suit le même schéma, on arrive à cela :

SELECT id, titre, jaquette, description, realisateur, acteurs, duree, annee, GROUP_CONCAT( intitule_genre SEPARATOR  ', '  ) AS genre, GROUP_CONCAT( intitule_origine SEPARATOR  ', '  ) AS origine
FROM serial_films, serial_films_l_genres, serial_genres, serial_origines,serial_films_l_origines
WHERE serial_films.id = serial_films_l_genres.id_film
AND serial_films.id = serial_films_l_origines.id_film
AND serial_films_l_genres.id_genre = serial_genres.id_genre_p
AND serial_films_l_origines.id_origine = serial_origines.id_origine_p
GROUP  BY id
LIMIT 0 , 30


Mais voilà lorsque j'execute cette requête, mon serveur MySQL rame dans le vide et n'affiche aucun résultat sachant que lorsque je veux récupérer que les genres, le résultat arrive en quelques centièmes de secondes.

Qu'en pensez vous ?

Merci d'avance pour votre aide.
Modifié par lellok (01 Jan 2010 - 23:20)
Bonjour,

D'abord merci d'utiliser les balises code en éditant ton message. Cela sera plus lisible pour tout le monde.

Ensuite tu dois faire attention les résultats qui vont sortir seront incorrect, d'ailleurs aucun résultat ne devrait pouvoir sortir, une erreur doit sortir normalement.
Tu ne précise pas de qu'elle table le champ "id" doit-il sortir. En plus si rame c'est normal. Je te conseille de te renseigner un peu sur les instructions INNER JOIN. Ici, si on imagine que tu as 100 entrée dans chacune de tes tables, cela signifie que le moteur mysql devra créé une pseudo table virtuelle de 100*100*100*100*100 soit 10 Milliards de lignes !!! Pas étonnant qu'elle pète un câble. Tout ça finir par faire un group by et récupérer qu'une trentaine de ligne.

Donc attention à l'avenir.

Pour information lier des tables dans un FROM avec seulement une virgule n'est plus sensé se faire depuis 1992. Change de livre ou de prof immédiatement !
Bonjour,

Merci de vos réponses, je me penche immédiatement sur le sujet. Je vous tiens au courant.

P.S : désolé pour la balise de Code, c'est corrigé Smiley smile
Je me suis remis à jour sur la structure des requêtes SQL et, effectivement, j'avais du boulot Smiley smile

Ma requête est donc maintenant la suivante :

SELECT A.id, A.titre, A.jaquette, A.description, A.realisateur, A.acteurs, A.duree, A.annee, A.nb_vues, A.date_ajout, GROUP_CONCAT(C.intitule_genre
SEPARATOR ', ' ) AS genre, GROUP_CONCAT(E.intitule_origine
SEPARATOR ', ' ) AS origine
FROM serial_films A
INNER JOIN serial_films_l_genres B ON A.id = B.id_film
INNER JOIN serial_genres C ON B.id_genre = C.id_genre_p
INNER JOIN serial_films_l_origines D ON A.id = D.id_film
INNER JOIN serial_origines E ON D.id_origine = E.id_origine_p
GROUP BY A.id
LIMIT 0 , 30


Tout marche nickel, j'ai bien toutes les informations que je veux. Néanmoins, la requête met 14 secondes à charger ce qui est énorme et j'ai un deuxième souci, si jamais il y'a plusieurs genres associés au film alors le champ origine contient plusieurs fois l'information à la suite. (ex : France, France, France...le nombre dépend du nombre de genres).

Pensez-vous qu'il y'a un moyen de l'optimiser ? Si non, pensez-vous qu'il serait plus rentable d'effectuer 2 requêtes à la suite, une pour les genres et une pour les origines ? Sachant que chaque requête séparée prend environ 1 seconde.

Qu'en pensez-vous ?
Modifié par lellok (02 Jan 2010 - 00:10)