Importation fichier 8G en moins de 1h
momo
-
Reivax962 Messages postés 3672 Date d'inscription Statut Membre Dernière intervention -
Reivax962 Messages postés 3672 Date d'inscription Statut Membre Dernière intervention -
Bonjour, quelqu'un aurait une portion de code permettant d'importer un fichier csv de 500 Mo en moins de 30 min.
J'utilise le code suivant qui fait une journée pour importer un fichier de 223 Mo.
J'utilise le code suivant qui fait une journée pour importer un fichier de 223 Mo.
if (isset($_FILES["file"]['name'])) { $fileName = $_FILES["file"]["tmp_name"]; $row = 0; if ($_FILES["file"]["size"] > 0) { $file = fopen($fileName, "r"); while(($column = fgetcsv($file, $_FILES["file"]["size"]+1, ";")) !== FALSE) { $row ++ ; if($row>1){ $_PDO->beginTransaction(); try { $table = new classe_table(NULL,$column[0],$column[1],$column[2],$column[3],$column[4],$column[5],$column[6],$column[7],$column[8],$column[9],$column[10],$column[11],$column[12],$column[13]); $MANAGER->Add($table); if($MANAGER->_Reponse->_Etat == _REPONSE_ERROR_){ $_PDO->rollback(); }else{ // Validation de la transaction $_PDO->commit(); } } catch (PDOException $e) { die("Error: " . $e->getMessage()); } } } fclose($file); } }
A voir également:
- Importation fichier 8G en moins de 1h
- Fichier bin - Guide
- Fichier epub - Guide
- Fichier rar - Guide
- Comment réduire la taille d'un fichier - Guide
- Fichier .dat - Guide
4 réponses
yg_be
Messages postés
23541
Date d'inscription
Statut
Contributeur
Dernière intervention
Ambassadeur
1 584
bonjour, tu ne nous explique pas dans quoi se fait cette importation.
as-tu envisagé d'utiliser
as-tu envisagé d'utiliser
LOAD DATA INFILE?
Non je n'utilise pas de LOAD DATA INFILE
La portion de code que j'ai mis tout en haut recois le fichier depuis un formulaire html
et le code js se charge d'envoyer mon fichier à ma page php qui se charge d'inserer dans la base base]de données.
code html
code js
fichierController.php
La portion de code que j'ai mis tout en haut recois le fichier depuis un formulaire html
et le code js se charge d'envoyer mon fichier à ma page php qui se charge d'inserer dans la base base]de données.
code html
Télécharger : <input type="file" ngf-select="" ng-model="csvpFile" name="file" ngf-accept="'csv/*'" required="">
code js
$scope.upload1 = function(file, uploadUrl){
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.then(function(response) {
}, function(response) {
});
}
$scope.upload = function(){
var file = $scope.csvpFile;
console.log('file is ' );
console.dir(file);
var URI_CONTROLLER_FOLDER = '../Layers/Business/Controller/';
var uploadUrl = URI_CONTROLLER_FOLDER+'fichierController.php?ACTION=_TRAITEMENT_';
$scope.upload1(file, uploadUrl);
}
fichierController.php
if (isset($_FILES["file"]['name'])) {
$fileName = $_FILES["file"]["tmp_name"];
$row = 0;
if ($_FILES["file"]["size"] > 0) {
$file = fopen($fileName, "r");
while(($column = fgetcsv($file, $_FILES["file"]["size"]+1, ";")) !== FALSE) {
$row ++ ;
if($row>1){
$_PDO->beginTransaction();
try {
$table = new classe_table(NULL,$column[0],$column[1],$column[2],$column[3],$column[4],$column[5],$column[6],$column[7],$column[8],$column[9],$column[10],$column[11],$column[12],$column[13]);
$MANAGER->Add($table);
if($MANAGER->_Reponse->_Etat == _REPONSE_ERROR_){
$_PDO->rollback();
}else{
// Validation de la transaction
$_PDO->commit();
}
} catch (PDOException $e) {
die("Error: " . $e->getMessage());
}
}
}
fclose($file);
}
}
Bonjour,
Dans ton code, tu insères les données ligne par ligne en base.
N'as-tu pas le moyen de préparer toutes les données et de ne faire qu'un seul appel à la base de données ? (ou de les gérer par paquets plus gros, par exemple 500 lignes par 500 lignes, à déterminer pour optimiser mémoire utilisée et temps de traitement) ?
Autrement dit, sortir le $MANAGER->Add de la boucle, et n'y garder que le traitement sur $table ?
Comme je ne sais pas ce qu'est exactement ton $MANAGER ni classe_table(), je ne peux pas vraiment être plus précis, mais l'idée c'est de trouver l'équilibre optimal entre nombre d'appel à la base, taille des requête et empreinte mémoire.
Xavier
Dans ton code, tu insères les données ligne par ligne en base.
N'as-tu pas le moyen de préparer toutes les données et de ne faire qu'un seul appel à la base de données ? (ou de les gérer par paquets plus gros, par exemple 500 lignes par 500 lignes, à déterminer pour optimiser mémoire utilisée et temps de traitement) ?
Autrement dit, sortir le $MANAGER->Add de la boucle, et n'y garder que le traitement sur $table ?
Comme je ne sais pas ce qu'est exactement ton $MANAGER ni classe_table(), je ne peux pas vraiment être plus précis, mais l'idée c'est de trouver l'équilibre optimal entre nombre d'appel à la base, taille des requête et empreinte mémoire.
Xavier
Avec les fonctions telles qu'elles sont écrites, ça ne va pas être possible. Il faudrait les modifier, ou créer une fonction dédiée.
J'ai trouvé un code qui répond à ton problème (à adapter bien sûr, notamment sur la gestion des erreurs)
Sur la page suivante, regarde la réponse acceptée :
https://stackoverflow.com/questions/15069962/php-pdo-insert-batch-multiple-rows-with-placeholders/15070222#15070222
Par contre n'hésite pas à regarder du côté de ce que te suggère yg_be. Je ne connais pas du tout LOAD DATA INFILE mais vu le nom, ça a l'air dédié à ton usage, ce serait dommage de se priver d'une solution toute faite...
J'ai trouvé un code qui répond à ton problème (à adapter bien sûr, notamment sur la gestion des erreurs)
Sur la page suivante, regarde la réponse acceptée :
https://stackoverflow.com/questions/15069962/php-pdo-insert-batch-multiple-rows-with-placeholders/15070222#15070222
Par contre n'hésite pas à regarder du côté de ce que te suggère yg_be. Je ne connais pas du tout LOAD DATA INFILE mais vu le nom, ça a l'air dédié à ton usage, ce serait dommage de se priver d'une solution toute faite...
la classe
code d'insertion
class classe_table {
private $champ1 ;
private $champ2 ;
private $champ3 ;
private $champ4 ;
private $champ5 ;
function __construct ($champ1,$champ2,$champ3,$champ4,$champ5) {
$this->champ1 = $champ1 ;
$this->champ2 = $champ2 ;
$this->champ3 = $champ3 ;
$this->champ4 = $champ4 ;
$this->champ5 = $champ5 ;
}
function getchamp1(){ return $this->champ1 ; }
function getchamp2(){ return $this->champ2 ; }
function getchamp3(){ return $this->champ3 ; }
function getchamp4(){ return $this->champ4 ; }
function getchamp5(){ return $this->champ5 ; }
function setchamp1($value) { $this->champ1 = $value ; }
function setchamp2($value) { $this->champ2 = $value ; }
function setchamp3($value) { $this->champ3 = $value ; }
function setchamp4($value) { $this->champ4 = $value ; }
function setchamp5($value) { $this->champ5 = $value ; }
}
code d'insertion
function Add(table $table ){
$retour = FALSE;
$sql="Call table_ADD(:champ1,:champ2,:champ2,:champ3,:champ4,:champ5)";
$parametre=array(":champ1"=> $table->getchamp1(),":champ2"=> $table->getchamp2(),":champ3"=> $table->getchamp3(),":champ4"=> $table->getchamp4(),":champ5"=> $table->getchamp5());
Log::writeLog(_RESSOURCE_FOLDER_,"SQL","SQL-REQUETTE",array(parent::SqlClarifyParametre($sql,$parametre)));
try {
$requette=$this->_PDO->prepare($sql);
$retour=$requette->execute($parametre);
if($retour) {
$this->_Reponse = new Reponse(_REPONSE_SUCCES_ ,array(array($this->_LANGUAGE_["table"]["@INSERT_SUCCES"])),$table) ;
}
else {
$this->_Reponse = new Reponse(_REPONSE_ERROR_ ,array(array($this->_LANGUAGE_["table"]["@INSERT_FAILED"])),$table) ;
}
} catch (PDOException $ex) {
$this->_Reponse = new Reponse(_REPONSE_ERROR_,array(array("PDO",$ex->getMessage())),$table);
}
return $retour;
}