Videos streaming images jeux et buzz
Connexion






Perdu le mot de passe ?

Inscrivez-vous maintenant !
Menu Principal
Communauté


(1) 2 »


Wiliwilliam
BDD + php éviter d'effectuer 300 requêtes
 1  #1
La loi c'est moi
Inscrit: 07/04/2012 19:19
Post(s): 30134
Karma: 8637
ça va pas être évident de situer le contexte donc je vais simplifier. donc j'ai ... 2 foreach imbriqués (ça commence bien :-D)

foreach(un gros TABLEAU A qui déroule des pseudos){
     A chaque pseudo, une requête api qui nous ramène un gros TABLEAU B contenant 10 TABLEAUX C
     foreach(déroule le TABLEAU B qui nous affiche les TABLEAU C un par un){
           dans les tableaux C on récupère des données
           ces données on les additionne sur les 10 tableaux
           par exemple la valeur A1 du premier tableau C s'additionne avec la valeur A1 du deuxième tableau C ...etc 
     }
     on se retrouve avec les valeurs des 10 tableaux, additionnées.
     on envoie tout ça dans une BDD avec comme clé uniquement le pseudo et derrière toutes les valeurs additionnées

}


Jusque là tout va bien ça fait pas mal de requêtes API et SQL mais il n'y a que 30 pseudos.

Donc
TABLEAU A => 30 pseudos
-> requête
TABLEAU B => 10 TABLEAUX C
TABLEAU C => des variables

La où ça se corse, c'est que dans le TABLEAU C il y a une variable PSEUDO (qui n'a rien à voir avec le pseudo du TABLEAU A).
Et moi, ce que je veux faire, c'est créer une seconde table dans ma BDD qui stocke les valeurs du TABLEAU C en fonction du PSEUDO qui se trouve dans le TABLEAU C.
/!\ dans les 30x10 TABLEAUX C on peut retrouver très facilement plusieurs fois un même pseudo.

Et pour le moment, la seule technique que j'ai trouvé c'est d'envoyer un update vers la seconde table dans le FOREACH qui déroule le TABLEAU B et qui affiche les TABLEAUX C 1 par 1, avec les infos du TABLEAU C qui est en train d'être affiché.

Mais du coup, ça fait 30x10 requêtes, c'est quand même méga moche.

/!\le problème c'est que la liste des pseudos possibles dans le tableau est supérieur à 100..../!\

Donc voilà où j'en suis.
Actuellement je regarde comment faire pour créer un tableau php avec en clé le pseudo du tableau C et en "valeurs" les variables du tableau C qui s'additionnent à chaque boucle du premier et deuxième foreach. mais j'ai aucune idée de comment mettre ça en place.


donc HELP 😃
j'ai vraiment essayé d'être clair mais je peux être plus précis et mettre mon code sur pastbin si vraiment y a besoin

Contribution le : 19/08/2016 00:02
Signaler

Noemus
 0  #2
Je suis accro
Inscrit: 09/01/2007 18:11
Post(s): 510
:-o

EDIT : @Wiliwilliam_ Les 2 ! 😃

@Wiliwilliam_ Merci d'éclairer ma lanterne et bon courage ! 🙂

Contribution le : 19/08/2016 00:46
Signaler

Wiliwilliam
 0  #3
La loi c'est moi
Inscrit: 07/04/2012 19:19
Post(s): 30134
Karma: 8637
@Noemus genre wtf c'est quoi ce foutoir ou wtf qu'est ce qu'il nous raconte le gars?


je vais expliciter le contexte du coup.
@Noemus

le TABLEAU A: c'est la liste des pseudos des joueurs de League of legends koreusiens. (en fait c'est des IDs mais on s'en tape)

la requête API récupère le TABLEAU B : les 10 dernières parties du joueur. les 10 TABLEAUX C étant les 10 dernières parties.

Du coup dans la seconde boucle, je récupère les stats des 10 parties pour en faire une moyenne, et je balance tout ça dans une BDD. Ensuite je passe au joueur suivant ...etc

Et dans chaque partie, le joueur incarne un personnage.
Et moi ce que je veux faire c'est des stats de ces personnages mais sur l'ensemble des joueurs koreusiens, donc des stats sur 300 parties.
(il y a actuellement 133 champions que l'on peut incarner dans le jeu)

Contribution le : 19/08/2016 01:05
Signaler

-JoJo-
 0  #4
Je masterise !
Inscrit: 25/12/2007 00:19
Post(s): 4643
Karma: 1546
De nos jours, on ne fais plus vraiment des requêtes SQL manuellement, on utilise des framework ORM. Il feront le boulot à ta place, ton code sera bien plus simple et surtout bien plus efficace.

Je comprends pas vraiment le contexte mais grosso modo, quand tu fais des SELECT, n'utilise pas * mais récupère les seuls champs que tu vas aider.

Disons t'as une table User avec les champs id, pseudo, prénom, âge, ...
Si t'as besoin que de l'ID ou pseudo, fait un SELECT id, pseudo FROM ...

Je ne comprends toujours pas ton contexte.

Ensuite, ça m'a l'air plus d'un algorithm et présenter les données aux personnes.
Ce genre de tasques doit se faire dans un service, dans un autre process que le serveur qui traite les requêtes HTML. Tu prépares les données dans une base données et tes APIs renvoient ces données sans faire de traitement.

Tu utilses quel framework?

Sinon, tu peux aussi utiliser les triggers dans MySQL. Je suis sure ça peut s'appliquer dans ton cas. Regarde ici :
http://dev.mysql.com/doc/refman/5.7/en/trigger-syntax.html

Contribution le : 19/08/2016 06:36
Signaler

Khalyo
 0  #5
Je viens d'arriver
Inscrit: 18/11/2014 20:20
Post(s): 5
C'est pas super clair mais d'après ce que j'ai compris :

Si tu peux modifier l'API, tu peux essayer de faire en sorte qu'elle te renvoie directement ces stats?

Tu peux utiliser SQL pour calculer directement le résultat souhaité. Par exemple : tu fais un avg sur tes 10 dernières parties dans le SQL et tu renvoies cette moyenne. Elle sera calculée de manière bien plus rapide et t'évite de faire ton 2nd foreach.

Contribution le : 19/08/2016 07:52
Signaler

-Flo-
 0  #6
Je poste trop
Inscrit: 08/01/2005 13:41
Post(s): 10977
Karma: 3321
Je pense que vous n'avez pas bien compris. Il récupère des données via une API externe, et souhaite ensuite les stocker en base. Son problème est qu'il doit réaliser 10 appels par personne pour récupérer ses données, et qu'il veut éviter d'en faire 10 requêtes mysql par personne pour les stocker en base.

@Wiliwilliam_ : Sans en savoir plus sur la structure et la logique de ces données, et la structure de la table de destination, difficile de t'aider de manière détaillée. Mais à vue de nez, une piste que tu pourrais explorer est d'écrire au fur et à mesure les résultats de tes appels dans un fichier. Puis lorsque tu as terminé la phase de récupération des données, de charger en une seule fois le contenu de ce fichier dans ta base en utilisant la commande mysql LOAD DATA.

Contribution le : 19/08/2016 08:49
Signaler

Arsenick
 0  #7
J'aime glander ici
Inscrit: 13/12/2006 00:12
Post(s): 6011
Karma: 747
@Wiliwilliam_
Je rejoins (une fois n'es tpas coutume) @-Flo- :ta logique devrait être inversée:
Foareach (tableB->lines as lineB){
    Foreach (lineB->lines as lineC){
        process lineC
    }
}


L'avantage c'est que tu ne parse qu'une seule fois tes tableaux B et C.

L'idée de @-Flo- va aussi te permettre de gagner en vitesse d'exécution: ne pas faire l'update du Tableau A direct mais tu stock tout tes tableaux C en séquentiel dans un fichier ou une table temporaire et fin de journée (semaine/mois/année/siècle/millénaire 😃 ), tu bulk update A à partir du séquentiel de C.

Tente de séparer au maximum ton appli en petit bloc que tu assemble par la suite:
- Bloc 1 : Lire les données.
- Bloc 2 : Traiter les données.
- Bloc 3 : Stocker les données.

Faire Lire - traiter - stocker en un seul bloc, tu va te retrouver avec un code moche et casse-gueule et surtout ne tente pas de faire un truc otpi au premier jet: t'as 8 fois le même bout de code copier/coller? c'est pas grave, il y a le refactoring pour optimiser le code 🙂.

Contribution le : 19/08/2016 11:34
Signaler

Wiliwilliam
 0  #8
La loi c'est moi
Inscrit: 07/04/2012 19:19
Post(s): 30134
Karma: 8637
je vous ai fait un pastbin du coup, parce lorsque je vois le code de arsenick, je me rends compte que j'ai vraiment expliqué comme un gros noeud 😃
http://pastebin.com/nQFRHpMd

avec un GROS mémo dans la seconde boucle.
y a pleins de commentaire. j'aimerais que vous y jetiez un coup d'oeil si vous avez le temps l'envie et la patience 😃.
L'endroit où j'ai fais le gros commentaire destiné à -flo- est l'endroit où je suis censé récupérer les infos sur les CHAMPIONS pour les stocker dans la TABLE DES CHAMPIONS.
la table lolkoreus étant la TABLE DES JOUEURS.

La base de mes champions est organisée comme pour les joueurs sauf qu'il y a l'ID du champion et pas l'ID d'un joueur.

Contribution le : 19/08/2016 11:39
Signaler

Arsenick
 1  #9
J'aime glander ici
Inscrit: 13/12/2006 00:12
Post(s): 6011
Karma: 747
@Wiliwilliam_ Tu saurais nous dire si tu te sers d'un FW et sur quel archi?

je vais éditer ce messages au fur et à mesure de lecture du code, histoire de pas post en rafale 😃



-
ini_set('error_log', dirname(__file__) . '/log_error_php.txt');


l'error log est config côté serveur normalement, pas côté appli. Même avec 50 appli sur le même serveur t'es pas censer avoir 300 lignes de log par jours (ou alors t'as un gros soucis :D).


- de même un best practice (BP):
$user="xxx";

=>
CONST $user="xxx";


Ca t'évite de le modif par erreur.


//liste des joueurs 
$pseudolist=array( dumonde^^);

//déclaration de la chaîne de pseudp
$pseudos="";

//incrémentation des pseudos pour la requête groupée des ID
foreach($pseudolist as $name){
    $pseudos.=strtolower($name).',';
}

//on enlève la virgule de trop à la fin
$pseudos=substr($pseudos,0,-1);



WTF? tu recrée un array à partir d'un array que tu crée toi même :gratte: C'est quoi le but?
- Ton lower case est inutile puisque ton array est crée manuellement (le gars qui met une maj à la main tu le frappe stout! :D)
- Tu concatène une virgule pour ensuite la retirée?

Contribution le : 19/08/2016 11:45
Signaler

Wiliwilliam
 0  #10
La loi c'est moi
Inscrit: 07/04/2012 19:19
Post(s): 30134
Karma: 8637
@Arsenick

t'arrêtes pas, je prends des notes 😃

edit : pour l'array 'faut pas chercher, le document est temporaire, plus tard les koreusiens pourront stocker leur pseudo sans que j'ai à manuellement l'inscrire dans le script.
le foreach disparaitra et ça sera une requête sql
et effectivement, ça sert absolument à rien ici, c'était juste pour me rappeler la syntaxe du foreach, :roll: me juge pas s'il te plaît :lol:

Contribution le : 19/08/2016 11:48
Signaler

-Flo-
 1  #11
Je poste trop
Inscrit: 08/01/2005 13:41
Post(s): 10977
Karma: 3321
@Wiliwilliam_ : Dans ce cas ne réalise pas le load data directement dans ta table de destination, mais dans un premier temps dans une table temporaire. Et dans un second temps, insère les données de cette table temporaire dans ta table de destination en réalisant les opérations de ton "ON DUPLICATE KEY" existantes.

En gros :

1/ DROP TABLE IF EXISTS lolkoreus_wrk
2/ CREATE TABLE lolkoreus_wrk LIKE lolkoreus
3/ LOAD DATA LOCAL INFILE '/chemin/de/ton/fichier' INTO TABLE lolkoreus_wrk
4/ INSERT INTO lolkoreus SELECT * FROM lolkoreus_wrk ON DUPLICATE KEY UPDATE etc.
5/ DROP TABLE lolkoreus_wrk

Contribution le : 19/08/2016 11:55
Signaler

Cornflake
 1  #12
Je masterise !
Inscrit: 29/04/2008 21:35
Post(s): 2544
Karma: 927
@Wiliwilliam_ Je ne comprend pas le soucis sur ton commentaire...Si tu fais ignore, tu as un doublon, et avant d'insérer le résult en DB,il suffit de boucler pour vérifier si il a des doublons, si il y en a, tu additiones/fait ce que tu veux avec les résultats, non ?
EDIT : Bon,j'ai un train de retard là 😃

Contribution le : 19/08/2016 11:56
Signaler

Wiliwilliam
 0  #13
La loi c'est moi
Inscrit: 07/04/2012 19:19
Post(s): 30134
Karma: 8637
@-Flo- huu ok ok j'avais pas pigé le coup de la table temporaire....

ok donc ça règle radicalement le soucis...
je fais ça et je vous tiens au courant.

@Cornflake t'inquiètes, ça compte quand même 😃

Contribution le : 19/08/2016 11:58
Signaler

-Flo-
 1  #14
Je poste trop
Inscrit: 08/01/2005 13:41
Post(s): 10977
Karma: 3321
@Wiliwilliam_ : Et pour ton histoire de liste de pseudos, pour info, tu as la fonction implode() qui te permet de créer une chaine à partir des valeurs d'un array.

Donc tes lignes 27 à 35 peuvent être remplacées par un simple $pseudos = implode(',', $pseudolist);

Contribution le : 19/08/2016 12:02
Signaler

Arsenick
 1  #15
J'aime glander ici
Inscrit: 13/12/2006 00:12
Post(s): 6011
Karma: 747
Citation :

@Wiliwilliam_ a écrit:
me juge pas s'il te plaît :lol:


Nullement, on a tous commencer avec un "hello world" et afficher un sapin de noel 🙂 => "Dont learn to code, code to learn!".

Mais si je peux te donner un conseil: php.net - foreach ça évite de "salir" ton code avec des trucs inutiles 🙂

Contribution le : 19/08/2016 12:05
Signaler

Wiliwilliam
 0  #16
La loi c'est moi
Inscrit: 07/04/2012 19:19
Post(s): 30134
Karma: 8637
@-Flo- 😢 je prends tarif sur ce coup entre toi et arsenick 🔨

en tout cas merci à tous pour le coup de main et les petites remarques de construction. c'est toujours super utile!!!

Contribution le : 19/08/2016 12:06
Signaler

Arsenick
 0  #17
J'aime glander ici
Inscrit: 13/12/2006 00:12
Post(s): 6011
Karma: 747
Citation :

@Wiliwilliam_ a écrit:
@-Flo- 😢 je prends tarif sur ce coup entre toi et arsenick 🔨


C'est pour ton bien :evil::-x :lol:

Citation :

@Wiliwilliam_ a écrit:
en tout cas merci à tous pour le coup de main et les petites remarques de construction. c'est toujours super utile!!!


Pas de soucis 🙂 hésite pas si besoin, je ne suis pas sur de toujours pouvoir t’apporter une solution par contre ^^.

Contribution le : 19/08/2016 12:14
Signaler

Wiliwilliam
 0  #18
La loi c'est moi
Inscrit: 07/04/2012 19:19
Post(s): 30134
Karma: 8637
Citation :

@-Flo- a écrit:
1/ DROP TABLE IF EXISTS lolkoreus_wrk
2/ CREATE TABLE lolkoreus_wrk LIKE lolkoreus
3/ LOAD DATA LOCAL INFILE '/chemin/de/ton/fichier' INTO TABLE lolkoreus_wrk
4/ INSERT INTO lolkoreus SELECT * FROM lolkoreus_wrk ON DUPLICATE KEY UPDATE etc.
5/ DROP TABLE lolkoreus_wrk


ok donc j'ai fait un fichier csv qui a cette gueule:

championId;indicea;indicen;wina;winn;assistsa;assistsn;......etc
421;0;1;0;1;0;12;0;6;0;7;0;43;0;13536;0;2150;0;0;0;0;0;0\n
157;0;1;0;0;0;14;0;16;0;15;0;292;0;28237;0;4094;0;1;0;0;0;0\n
111;0;1;0;1;0;37;0;22;0;18;0;372;0;45001;0;6624;0;0;0;0;0;0\n
35;0;1;0;1;0;41;0;28;0;21;0;445;0;57749;0;8481;0;0;0;0;0;0\n
31;0;1;0;0;0;51;0;39;0;27;0;702;0;74553;0;10497;0;0;0;0;0;0\n
80;1;0;0;0;25;51;15;39;20;27;39;702;15708;74553;1776;10497;1;0;1;0;0;0\n
268;0;1;0;1;25;55;15;50;20;27;39;988;15708;90458;1776;12248;0;0;0;0;0;0\n
89;0;1;0;0;25;61;15;58;20;31;39;1042;15708;104240;1776;14342;0;0;0;0;0;0\n
15;1;0;0;0;38;61;23;58;30;31;109;1042;27083;104240;2956;14342;0;0;0;0;0;0\n
245;0;1;0;1;38;72;23;73;30;33;109;1125;27083;121458;2956;16578;0;0;0;0;0;0\n
74;1;0;1;0;25;0;8;0;4;0;88;0;13189;0;1339;0;0;0;0;0;0;0\n
25;1;0;1;0;61;0;16;0;8;0;125;0;24563;0;2517;0;1;0;0;0;0;0\n
268;1;0;1;0;80;0;27;0;23;0;234;0;42420;0;4452;0;1;0;1;0;1;0\n
268;1;0;0;0;95;0;33;0;35;0;266;0;52586;0;5632;0;0;0;0;0;0;0\n


j'importe dans la table lolchampion comme ça:

LOAD DATA LOCAL INFILE 'chemin/vers/le/fichier.csv'
INTO TABLE lolchampion_wks
FIELDS TERMINATED BY ';'
ENCLOSED BY '"'
LINES TERMINATED BY '\n' 
(championId, indicea, indicen, wina, winn, assistsa, assistsn, ........etc)


L'enregistrement dans la table est parfait à l'exception d'une chose, c'est qu'il y a plusieurs lignes avec le même ID.
L'ID 268 notamment, et quand je regarde la table, au lieu de voir un "indicea" à 2 et un "indicen" à 1 je vois uniquement un "indicea" à 1 et un "indicen" à 0.
Donc le système de la table temporaire sera cool pour stocker ensuite dans la table principale mais là j'ai un soucis en amont...


EDIT: je vais tester en virant l'unicité de l'id du coup :roll: je suis un peu un boulet parfois
EDIT 2: haa bah voilà 😃

Contribution le : 19/08/2016 17:48
Signaler

-Flo-
 1  #19
Je poste trop
Inscrit: 08/01/2005 13:41
Post(s): 10977
Karma: 3321
@Wiliwilliam_ : Ah oui, pour le coup c'est de ma faute, j'aurais dû y penser.

Remplace le 2/ par un CREATE TABLE lolkoreus_wrk AS SELECT * FROM lolkoreus WHERE 1=0

Le "CREATE ... AS SELECT" copie la structure de la table du select, sans ses indexes. Le 1=0 sert juste à ne pas alimenter la table ainsi créée.

Dans tous les cas, conserve bien la logique qui recrée ta table temporaire à chaque run, histoire de t'assurer de repartir à 0 (au cas où le run précédent aurait planté en laissant des données dans cette table).

Contribution le : 19/08/2016 18:23
Signaler

Arsenick
 0  #20
J'aime glander ici
Inscrit: 13/12/2006 00:12
Post(s): 6011
Karma: 747
Il y a une raison au fait de jouer avec une temp table et pas le faire avec un objet côté appli?

Parce qu'une temp table normalement c'est juste pour garder une trace de ce qui a déjà été traiter en cas de plantage de l'appli mais si à chaque cycle tu drop peu importe ce qu'elle contient, autant utiliser un objet php.

Contribution le : 19/08/2016 19:44
Signaler


 Haut   Précédent   Suivant
(1) 2 »






Si vous êtes l'auteur d'un élément de ce site, vous pouvez si vous le souhaitez, le modifier ou le supprimer
Merci de me contacter par mail. Déclaré à la CNIL N°1031721.