CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

Aide script php

inight
inight
Niveau 9
03 août 2015 à 15:54:40

Bonjour,

J'ai à ma disposition plusieurs grosses tables d'une BDD représentées très simplement de la forme suivante (j'ai inventé les noms mais la forme est là):

TABLE DEPART 
Année    |  code  |  x  |  a1  |  a2  |  a3  |  a4  |  a5 | ... |  a200
2015          1      x1    58     74      5     23    22            232
2015          1      x5    41      4     58     78    81            21
..................................................

Ces tables contiennent environ 200 colonnes de données (a1 - a200) et il y a environ 30 000 lignes

Le script consiste à déplacer toutes ces données dans diverses tables :
une pour la donnée :

TABLE DATA
id_data  |  code_data  |  info_data
   ...
  7330         a1      donnée concernant x
  7331         a2      donnée concernant y
...
  7530        a200     donnée concernant z

De même il y en a une pour le "x"

Et les valeurs sont encore dans une autre table :

TABLE STOCKAGE
id_data(foreign key) | id_x(foreign key)  | année | valeur
  7330                         541           2015     58
  7331                         632           2015     74
............

------------------
Fin de présentation
------------------

Donc le script est réalisé, mais je dois souvent faire des requêtes à la BDD (select pour savoir si la la donnée data/x/y existe déjà et si oui récupérer l'id sinon insérer data/x/y ).

Bref, dans l'algo, je cherche à récupérer toutes les colonnes (200 colonnes donc 200 requêtes d'insertion dans data), puis je récupère toutes les données pour les 30 000 lignes.
Ensuite pour chaque ligne je dois vérifier si le x n'existe pas déjà dans sa table (si oui je récupère son id sinon j’insère un nouveau). Avec 30 000 lignes ça veut dire que 30 000 select sont fait sur la table data. A la fin avec les id récupérés et les années je peux insérer dans la table de stockage ce qui donne encore 30000lignes*200colonnes de requêtes d'insertion.

Est-ce normal d'avoir autant de requête ou c'est mon code/algo qui est vraiment nul ?

Par ailleurs j'ai fait des tests sur un fichier 200colonnes*1500 lignes le script fonctionne mais pour un fichier 200colonnes*30000lignes il y a une erreur "Fatal error: Allowed memory size of xxxxx bytes exhausted ".
Cela fonctionne en augmentant la max_memory_limit à 1024M mais cela pose probablement des risques pour le serveur ?
Comment gérer ça sinon ? Sachant que l'erreur arrive lorsque j'essaye de récupérer les 30000*200 données dans un tableau, j'ai essayé de découper en récupérant les 5000 premières lignes et ainsi de suite mais le script génère toujours cette erreur, que ce soit 5000, 2000 ou 500.

Merci d'avance pour votre aide !

Message édité le 03 août 2015 à 15:55:41 par inight
Darkandgel
Darkandgel
Niveau 10
03 août 2015 à 17:10:05

Ca sent surtout le defaut de conception.

une table avec 200 colones c'est deja moyen.
Mais en plus répliquer des données a droites a gauche...

inight
inight
Niveau 9
03 août 2015 à 17:31:13

Oui je n'ai pas précisé vraiment le contexte.
En fait je suis dans une petite boite et je ne gère pas la bdd (elle était déjà existante). La personne qui la gère reçoit des données et pour aller vite les place dans une table d'une manière proche de la "table départ" que j'ai présentée.

Cette personne a vue que cette façon de faire était rapide mais mauvaise, il avait donc préparé une autre conception mais n'a pas le temps de la remplir.

Il souhaite donc que toutes les données des tables mal conçues (celles avec 200 colonnes de données) soient déplacées vers des tables mieux pensées, le tout à l'aide d'une petite interface

Message édité le 03 août 2015 à 17:32:20 par inight
inight
inight
Niveau 9
03 août 2015 à 17:44:07

Je me demande donc si c'est possible/normal qu'un script fasse autant de requêtes ou je m'y prend mal ?
De plus je bloque à cette erreur de mémoire, je ne sais pas si ça peut-être dangereux de faire un ini_set("1024M") pour le serveur ?
Sachant que l'erreur vient au moment de récupérer les 200*30000données et que même en essayant de découper la récupération (2000lignes par 2000lignes), le script va bloquer.
Voici le code le morceau de code que je teste :

for($repetition=0;$repetition<$algoRepetitions;$repetition++)
{   
        echo "Garbage Colletor enabled : " . (gc_enabled() ? 'OUI' : 'NON') . "<br/>"; 
        $donnees = recupererDonneesTable($schema_origine,$table_origine,$repetition,2000); 
        unset($donnees);
        echo "Collect cycles : " . gc_collect_cycles() . "<br/>";
        echo 'Mem après collect_cycles : ' . number_format(memory_get_usage(), 0, '.', ',') . " octets<br/>";    
        echo "Memory peak : ".memory_get_peak_usage()." <br/>";
};
function recupererDonneesTable($schema,$table,$repetition,$nbLignesMax)
{    
      $debut = $repetition*2000;           
      $requete= "SELECT * FROM ".$schema.".".$table." OFFSET ".$debut." LIMIT ".($debut+2000);
      return resultatRequete($requete); 
}  

et l'erreur générée :

Garbage Colletor enabled : OUI
Collect cycles : 0
Mem après collect_cycles : 360,072 octets
Memory peak : 55335928 

Garbage Colletor enabled : OUI
Collect cycles : 0
Mem après collect_cycles : 360,072 octets
Memory peak : 110338080 

Garbage Colletor enabled : OUI
Collect cycles : 0
Mem après collect_cycles : 360,072 octets
Memory peak : 165466800 

Garbage Colletor enabled : OUI
Collect cycles : 0
Mem après collect_cycles : 360,072 octets
Memory peak : 220399040 

Garbage Colletor enabled : OUI

Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 32 bytes) in  
Darkandgel
Darkandgel
Niveau 10
03 août 2015 à 19:18:42

$debut = $repetition*2000;

$requete= "SELECT * FROM ".$schema.".".$table." OFFSET ".$debut." LIMIT ".($debut+2000);

T'es sur que c'etait pas
$debut = $repetition*2000; $requete= "SELECT * FROM $schema.$table OFFSET $debut LIMIT(2000);

Que tu voulais ecrire ?
Parce que la tu recuperes a chaque iteration 2000 lignes de plus qu'a la précédente

Sinon, concernant la "propreté" du script, si j'ai bien compris c'est juste un truc a passer une fois pour remettre la base dans un etat pas trop dégueu. Donc on s'en cogne que ce soit fait comme un sagouin, que les valeurs soient hardcodées et que le code soit crade

Message édité le 03 août 2015 à 19:21:36 par Darkandgel
inight
inight
Niveau 9
03 août 2015 à 23:44:37

A l'origine je récupérais directement les 30000 lignes de données seulement le script plantait "Problème allocation memoire".
Je me suis donc dit que je pouvais lire les 2000 premières lignes, faire les traitements, puis faire les 2000 lignes suivantes, les traiter, etc...

C'est cette technique que j'ai postais, mais elle ne fonctionne pas non plus vers 8000lignes le script plante également , voici le suivi de l'exécution


Garbage Colletor enabled : OUI   //lignes 0-2000 
Collect cycles : 0
Mem après collect_cycles : 360,072 octets
Memory peak : 55335928 

Garbage Colletor enabled : OUI //lignes 2000-4000
Collect cycles : 0
Mem après collect_cycles : 360,072 octets
Memory peak : 110338080 

Garbage Colletor enabled : OUI   //4000-6000 lignes
Collect cycles : 0
Mem après collect_cycles : 360,072 octets
Memory peak : 165466800 

Garbage Colletor enabled : OUI //lignes 6000-8000
Collect cycles : 0
Mem après collect_cycles : 360,072 octets
Memory peak : 220399040 

Garbage Colletor enabled : OUI //lignes 8000-10000

Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 32 bytes) in  

Sinon oui le but c'est que ce script soit utilisé pour remettre la bdd propre, mais le script sera toujours utilisé de temps en temps

Est-ce donc dangereux de faire un set_ini("1024M") ce qui fait fonctionner le script ? Cela pourrait-il faire planter le serveur ou autre ?

Message édité le 03 août 2015 à 23:46:39 par inight
Pseudo supprimé
Pseudo supprimé 22 août 2015 à 20:47:42

J'ai l'impression qu'il y a un défaut de conception, une table avec 200 colonnes c'est très étrange.

Sous forums
  • Aide à l'achat Mac
  • Création de sites web
  • Internet
  • Macintosh
  • Création de Jeux
  • Linux
  • Programmation
  • Steam Deck
  • Hardware
La vidéo du moment