Requête trop longue

Fermé
tybmhi Messages postés 200 Date d'inscription dimanche 13 juillet 2008 Statut Membre Dernière intervention 18 septembre 2017 - 17 mai 2012 à 17:41
 A.Nonymous - 18 mai 2012 à 22:57
Bonjour,

J'utilise cette requête pour calculer le nombre de pages pour un affichage des mes données. Cette requête est très longue (environ 20 secondes à s'effectuer). J'ai essayé avec "mysql_fetch_assoc" et "mysql_fetch_array" mais rien n'y fait. Je ne comprend pas pourquoi cette requête est aussi longue alors qu'utilisée dans un WHILE elle passe très vite.... Si quelqu'un pouvait m'aider, se serait sympa. Merci d'avance !

$retour = mysql_query("SELECT COUNT(*) AS nb_messages FROM table_1 WHERE createur != '$createur' AND reference NOT IN (SELECT reference FROM  table_2 WHERE trouveur = '$createur')");

$donnees = mysql_fetch_assoc($retour);$totalDesMessages = $donnees['nb_messages'];
// On calcule le nombre de pages à créer
$nombreDePages  = ceil($totalDesMessages / $nombreDeMessagesParPage);





10 réponses

gardiendelanuit Messages postés 1769 Date d'inscription jeudi 20 décembre 2007 Statut Membre Dernière intervention 19 novembre 2016 264
17 mai 2012 à 18:18
Bonjour,
20 secondes me paraît long... Tu as beaucoup de résultats dans ta BDD? Sinon c'est un serveur pro ou perso?
0
tybmhi Messages postés 200 Date d'inscription dimanche 13 juillet 2008 Statut Membre Dernière intervention 18 septembre 2017 12
17 mai 2012 à 18:29
Bonjour gardiendelanuit et merci de m'aider. C'est un serveur pro et pour la table 1 environ 1165 résultat et pour la table 2 environ 18000. Je ne pense pas que se soit vraiment énorme, non ? Qu'en penses tu ?
0
gardiendelanuit Messages postés 1769 Date d'inscription jeudi 20 décembre 2007 Statut Membre Dernière intervention 19 novembre 2016 264
Modifié par gardiendelanuit le 17/05/2012 à 18:46
18 000 c'est respectable mais quand même assez peu pour mettre autant de temps (cela dépend du serveur BDD et/ou de sa fréquentation.
Je ne connais pas le modèle schématique de ta BDD, donc je ne peux donc pas réellement savoir comment optimiser ta requête (s'il y a lieu d'être).

Merci de mettre "Résolu" quand nos réponses vous ont satisfaites!
La connaissance c'est comme la confiture: moins on en a et plus on l'étale.
0
tybmhi Messages postés 200 Date d'inscription dimanche 13 juillet 2008 Statut Membre Dernière intervention 18 septembre 2017 12
17 mai 2012 à 18:52
Alors apparemment en faisant le choix du NOT IN, j'ai pas choisi le top. Il faudrait que je fasse une jointure... Du type :

SELECT a.nom, a.prenom
FROM
Salarie a
LEFT OUTER JOIN Fonction b
ON b.nom = a.nom
AND b.job = `INFORMATICIEN'
WHERE b.nom IS NULL


Je n'ai jamais utilisé de jointure alors si tu as une idée de la chose je suis preneur. Encore merci.
0
gardiendelanuit Messages postés 1769 Date d'inscription jeudi 20 décembre 2007 Statut Membre Dernière intervention 19 novembre 2016 264
Modifié par gardiendelanuit le 17/05/2012 à 19:06
SELECT COUNT(*) AS nb_messages FROM table_1 A INNER JOIN table_2 B ON A.createur=B.trouveur WHERE A.createur != '$createur' AND A.reference...
Mais je ne suis pas sur du tout: je ne sais pas ce que tu cherches exactement dans la table le mieux serait que j'ai connaissance de chaque table avec leurs relation puis ce que tu veux obtenir.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
tybmhi Messages postés 200 Date d'inscription dimanche 13 juillet 2008 Statut Membre Dernière intervention 18 septembre 2017 12
17 mai 2012 à 19:26
Vraiment sympa de ta part. je vais essayer d'être précis. Alors j'ai deux tables, une qui se nomme "chasse_enigme" (table 1) dans laquelle on retrouve les énigmes postées par les internautes. Dans la deuxième table, nommé "chasse_victoire", on retrouve les bonne réponses des internautes qui ont résolus une énigme. Ce que je veux faire c'est afficher uniquement les énigmes que l'internaute n'a pas encore trouvé et qui ne sont pas les siennes (qu'il n'a pas posté lui-même).
Pour cela, je prend toutes les références des énigmes de la table "chasse_enigme" en retirant ses propres énigmes (WHERE createur != '$createur') et je retire toutes les références des énigmes se trouvant dans la table "chasse_victoire" qui porte le nom de l'internaute qui fait afficher la liste des énigmes qu'il n'a pas encore résolu.

Dans la table "chasse_enigme" on retrouve une colonne "reference" (c'est en fait le numéro de l'énigme). Et une colonne "createur" qui correspond à l'internaute qui a posté l'énigme.

Dans la table "chasse_victoire" on retrouve la même colonne "reference" avec aussi le nom de l'internaute qui a bien répondu dans une colonne nommée "trouveur".

PS : La variable '$createur' correspond juste à l'internaute.

N'hésite pas à me demander des précisions. Vraiment merci !
0
gardiendelanuit Messages postés 1769 Date d'inscription jeudi 20 décembre 2007 Statut Membre Dernière intervention 19 novembre 2016 264
17 mai 2012 à 20:24
SELECT COUNT(*) as "nb_message" FROM chasse_enigme E INNER JOIN chasse_victoire V ON E.reference=V.reference  WHERE E.createur != '.$createur.' AND V.trouveur != '.$createur.' ;
Je pense.
0
tybmhi Messages postés 200 Date d'inscription dimanche 13 juillet 2008 Statut Membre Dernière intervention 18 septembre 2017 12
17 mai 2012 à 21:01
Yes !! La requête est beaucoup plus rapide. Cependant, j'ai beaucoup plus de pages que prévu (750 au lieu de 70). J'ai essayé aussi comme ceci car je pense que le V.trouveur doit être égale au $createur :

$retour = mysql_query("SELECT COUNT(*) AS nb_messages FROM chasse_enigme E INNER JOIN chasse_victoire V ON E.reference=V.reference WHERE E.createur != '.$createur.' AND V.trouveur = '.$createur.' ");

Mais là plus rien ne s'affiche. En fait, je pense que la soustraction n'a pas lieu. On ne retire pas les énigmes résolue des énigmes totales.

0
Navid_92 Messages postés 711 Date d'inscription dimanche 7 décembre 2008 Statut Membre Dernière intervention 12 février 2015 87
Modifié par Navid_92 le 17/05/2012 à 21:18
Le magicstérix (*) est à éviter, il vaut mieux le remplacer par le nom d'une colonne qui s'autoincrémente, par exemple la colonne id.

Après il y a une erreur de concaténation dans ton code.

Voici la version corrigée:

<?php 
# Préparation de la requête 
$query = "SELECT COUNT(*)  
         AS nb_messages  
         FROM chasse_enigme  
         E  
         INNER JOIN chasse_victoire  
         V  
         ON E.reference=V.reference  
         WHERE  
         E.createur != '".$createur."'  
         AND  
         V.trouveur = '".$createur."'"; 
     
# Execution de la requête 
$result = mysql_query($query ) or die(mysql_error()); 

# Récupération du nombre de résultats 
$data = mysql_fetch_assoc($result); 
$totalDesMessages = (int)$data['nb_messages']; 

# Calcul du nombre de pages à créer 
$nombreDePages  = ceil($totalDesMessages / $nombreDeMessagesParPage); 
?>

Amicalement Navid, alias DestEN-
.::. Contributeur Sécurité Niveau Intermédiaire .::.
0
tybmhi Messages postés 200 Date d'inscription dimanche 13 juillet 2008 Statut Membre Dernière intervention 18 septembre 2017 12
Modifié par tybmhi le 18/05/2012 à 20:23
Merci pour ton aide Navid_92 mais ça ne fonctionne toujours pas. J'ai passé ma journée à parcourir les forums et... rien !

Je veux juste retirer ce NOT IN qui fonctionne mais qui prend beaucoup trop de temps. Y aurait-il une bonne âme pour me refaire ce bout de code avec un LEFT OUTER JOIN, NOT EXIST ou quelques chose du genre ? C'est tout ce que j'ai vu dans les forums mais sans jamais y arriver.
Merci d'avance

$retour = mysql_query("SELECT COUNT(reference) AS nb_messages FROM chasse_enigme WHERE createur != '$createur' AND reference NOT IN (SELECT reference FROM chasse_victoire WHERE trouveur = '$createur')");



0
SELECT COUNT(*) AS nb_messages FROM table_1 WHERE createur != '$createur' AND reference NOT IN (SELECT reference FROM table_2 WHERE trouveur = '$createur')

Si je comprends bien, il faut :
- Compter le nombre de messages dont :
- createur = $createur
- aucun autre enregistrement ayant la même référence ait $createur en tant que trouveur, autrement dit, aucun autre message ayant même référence et même créateur en tant qu'ouvreur

SELECT
COUNT(1) nb_messages
FROM table_1
LEFT JOIN table_2 ON table_1.reference = table_2.reference AND table_1.createur = table_2.trouveur
WHERE
table_1.createur = '$createur'
AND table_2.trouveur IS NULL

Pour améliorer le temps de réponse là-dessus, il faut:
- INDEX sur createur
- INDEX sur trouveur
- INDEX sur reference

Il peut être préférable de faire table_2.<clé primaire> IS NULL dans le WHERE s'il existe une PK
0