[PHP] import dati

emanuelesalati

Nuovo Utente
23 Ott 2018
8
0
1
Buonasera,
devo importare, con un job, circa 300.000 righe da un database oracle ad sql server, ogni giorno, con codeigniter php.
Potete consigliarmi un metodo per farlo in modo sicuro e veloce.
Attendo vs grazie e buon lavoro a tutti
 
Come da specifiche potresti utilizzare l'insert batch nativo di CI:
PHP:
//conviene creare pacchetti da 100 / 200 dati
$this->db->insert_batch('tabella',$dati)

Naturalmente l'array "$dati" deve essere consistente e dovrà essere passato come array di array ossia:
PHP:
$dati=[
['nome'=>'nome'....],
['nome'=>'ciao'],
['cognome'=>'sempre']
];
Questo per farti vedere con non tutti i dati passati devono essere uguali.....

Proverei a creare un metodo ricorsivo per l'elaborazione, 300000 dati non sono tanti, diciamo che avendo due macchine in rete locale si fa abbastanza velocemente il travaso....
In alternativa salvi il tuo SQL in formato idoneo e lo dai in pasto al DB sempre tramite cron!
 
Come da specifiche potresti utilizzare l'insert batch nativo di CI:
PHP:
//conviene creare pacchetti da 100 / 200 dati
$this->db->insert_batch('tabella',$dati)

Naturalmente l'array "$dati" deve essere consistente e dovrà essere passato come array di array ossia:
PHP:
$dati=[
['nome'=>'nome'....],
['nome'=>'ciao'],
['cognome'=>'sempre']
];
Questo per farti vedere con non tutti i dati passati devono essere uguali.....

Proverei a creare un metodo ricorsivo per l'elaborazione, 300000 dati non sono tanti, diciamo che avendo due macchine in rete locale si fa abbastanza velocemente il travaso....
In alternativa salvi il tuo SQL in formato idoneo e lo dai in pasto al DB sempre tramite cron!
intanto grazie x la risposta cerco di spiegare meglio:
ho un db in locale dal quale posso prelevare questi record che andranno insertati in piu tabelle swl server su un database in cloud.
Conviene secondo te allora fare la insert secca su una tabella di appoggio di tutte le righe e poi scorrerla e popolare la tabella esatta a seconda del record che trovo; vorrei prevedere anche di andare in update se trovo già il dato!!
attendo tue e grazie ancora
 
Non ho capito cosa intendi fare
DB 1 -> dati da 1 tabella
DB 2-> dati dal DB 1 separati in più tabelle?
Se questo fosse il caso sarebbe meglio creare un modello per la gestione dei dati... Il controllo naturalmente deve essere effettuato row2row!

Segnati magari i record sul quale è stata effettuata una modifica così carichi solo le diff.!
 
Ciao,
db1 è un cursore che da più tabelle mi crea un set di record con un campo tipo record iniziale di 3 caratteri che mi indica cos’è quella riga e dove andrá. Nel db2 di destinazione è dove, a seconds della riga e sel tipo record, devo fare insert o update. è continuo questo scambio dati tutto il giorno, lo dovro mettere sotto iob e tenerlo sotto controllo.
che ne pensi? è prezioso il vs aiuto!
 
hai verificato la possibilità di collegare il db oracle come linked server nel sql server
e poi usare funzionalità di mirroring proprie di sql server ?
se riesci ad organizzare così, ti affidi a soluzioni native del db
 
hai verificato la possibilità di collegare il db oracle come linked server nel sql server
e poi usare funzionalità di mirroring proprie di sql server ?
se riesci ad organizzare così, ti affidi a soluzioni native del db
Buongiorno,
si l'ho valutato ma vorrei farlo senza esporre il db di Oracle quindi una macchina locale che accede al db Oracle e di conseguenza spara i dati su SQL serve che tanto è su server cloud quindi è pubblico.
Avevo pensato di creare n view su Oracle che mi interrogo come servizio da PHP ogni 10 minuti ad esempio ed aggiornare cosi il db su Sql Server, segnandomi cio che ho importato naturalmente.
E' la prima volta che devo fare una cosa del genere quindi sono aperto a tutto.
Grazie
 
Più che fare una sincronizzazione 1 volta al giorno, opterei per una schedulazione oraria così da evitare qualsiasi blocco.
Ipotizzando una linearità sulla quantità dei dati: 300000 / 12 (ore 07-19) = 25000 record da processare ogni ora.

Provando ad effettuare un piccolo test questi i risultati:
25000 record
1- Inserimento row2row ~ 793.5376 secondi.
2- Inserimento Batch ~ 14.4125 secondi

Come puoi vedere effettuando queste prove l'inserimento/aggiornamento sul db conviene farlo solo attraverso batch.

Cerco di spiegare il concetto della soluzione più veloce:
1- Hai 3 tabelle che vengono popolate a seconda della tipologia di record.
2- Recuperi tutto il contenuto dal DB1 e inizi a processare i dati
A questo punto aggiungerei un bit:
1- Memorizzo il dato già presente sul DB2 nel DB1 (vedi sotto)
2- Aggiungo un marcatore per la tipologia di dato nel DB1 "create/update/no_action" (nulla vieta 0,1,2)
3- Effettuo la query nel DB1 solo sui record non processati "create"
4- Effettuo la query nel DB1 solo sui record da aggiornare "update"
5- Una volta effettuate le operazioni necessarie sul DB2 aggiorno tutti (inteso come quelli passati) i dati del DB1 in "no_action" così da evitare di recuperarli al prossimo cron.

Fatto questo sia l'aggiornamento che l'inserimento risulteranno abbastanza veloci.

Prevedi 2 variabili nel modello di gestione dati:
PHP:
public $data_insert=[];
public $data_update=[];
Effettua tutta la porzione di codice che serve alla fine dividi l'array in pacchetti da 200/250 e inserisci/aggiorni in batch.

Credo sia abbastanza chiaro il concetto.!

Qui il codice (CI) per la verifica dei tempi, crea una tabella con id,text1,text2,text3,text4 e aggiungi nell'autoload l'helper string.
PHP:
private $num_rows=25000;
private $model=['text1','text2','text3','text4'];
private $data=[];
public function __construct() {
   parent::__construct();
   $this->crea_dati_inserimento();
}
public function crea_dati_inserimento(){
   for($i=0;$i<$this->num_rows;$i++){
      foreach ($this->model as $items){
         $this->data[$i][$items]=random_string('alnum',rand(5,20));
      }
   }
}

public function carica_dati_one_row(){
   set_time_limit(0);
   $this->benchmark->mark('code_start');


   foreach ($this->data as $k=>$v){
      $this->db->insert('table1',$v);
   }
   
   /**
    * Inserimento batch
    */
   /*
   $a=array_chunk($this->data,250);
   foreach ($a as $items){
      $this->db->insert_batch('table1',$items);
   }*/

   
   
   $this->benchmark->mark('code_end');

   echo $this->benchmark->elapsed_time('code_start', 'code_end');
}
 
Più che fare una sincronizzazione 1 volta al giorno, opterei per una schedulazione oraria così da evitare qualsiasi blocco.
Ipotizzando una linearità sulla quantità dei dati: 300000 / 12 (ore 07-19) = 25000 record da processare ogni ora.

Provando ad effettuare un piccolo test questi i risultati:
25000 record
1- Inserimento row2row ~ 793.5376 secondi.
2- Inserimento Batch ~ 14.4125 secondi

Come puoi vedere effettuando queste prove l'inserimento/aggiornamento sul db conviene farlo solo attraverso batch.

Cerco di spiegare il concetto della soluzione più veloce:
1- Hai 3 tabelle che vengono popolate a seconda della tipologia di record.
2- Recuperi tutto il contenuto dal DB1 e inizi a processare i dati
A questo punto aggiungerei un bit:
1- Memorizzo il dato già presente sul DB2 nel DB1 (vedi sotto)
2- Aggiungo un marcatore per la tipologia di dato nel DB1 "create/update/no_action" (nulla vieta 0,1,2)
3- Effettuo la query nel DB1 solo sui record non processati "create"
4- Effettuo la query nel DB1 solo sui record da aggiornare "update"
5- Una volta effettuate le operazioni necessarie sul DB2 aggiorno tutti (inteso come quelli passati) i dati del DB1 in "no_action" così da evitare di recuperarli al prossimo cron.

Fatto questo sia l'aggiornamento che l'inserimento risulteranno abbastanza veloci.

Prevedi 2 variabili nel modello di gestione dati:
PHP:
public $data_insert=[];
public $data_update=[];

[QUOTE="macus_adi, post: 205054, member: 35357"]Più che fare una sincronizzazione 1 volta al giorno, opterei per una schedulazione oraria così da evitare qualsiasi blocco.
Ipotizzando una linearità sulla quantità dei dati: 300000 / 12 (ore 07-19) = 25000 record da processare ogni ora.

Provando ad effettuare un piccolo test questi i risultati:
25000 record
1- Inserimento row2row ~ 793.5376 secondi.
2- Inserimento Batch ~ 14.4125 secondi

Come puoi vedere effettuando queste prove  l'inserimento/aggiornamento sul db conviene farlo solo attraverso batch.

Cerco di spiegare il concetto della soluzione più veloce:
1- Hai 3 tabelle che vengono popolate a seconda della tipologia di record.
2- Recuperi tutto il contenuto dal DB1 e inizi a processare i dati
 A questo punto aggiungerei un bit:
1- Memorizzo il dato già presente sul DB2 nel DB1 (vedi sotto)
2- Aggiungo un marcatore per la tipologia di dato nel DB1 "create/update/no_action" (nulla vieta 0,1,2)
3- Effettuo la query nel DB1 solo sui record non processati "create"
4- Effettuo la query nel DB1 solo sui record da aggiornare "update"
5- Una volta effettuate le operazioni necessarie sul DB2 aggiorno tutti (inteso come quelli passati) i dati del DB1 in "no_action" così da evitare di recuperarli al prossimo cron.

Fatto questo sia l'aggiornamento che l'inserimento risulteranno abbastanza veloci.

Prevedi 2 variabili nel modello di gestione dati:
[PHP]
public $data_insert=[];
public $data_update=[];
Effettua tutta la porzione di codice che serve alla fine dividi l'array in pacchetti da 200/250 e inserisci/aggiorni in batch.

Credo sia abbastanza chiaro il concetto.!

Qui il codice (CI) per la verifica dei tempi, crea una tabella con id,text1,text2,text3,text4 e aggiungi nell'autoload l'helper string.
PHP:
private $num_rows=25000;
private $model=['text1','text2','text3','text4'];
private $data=[];
public function __construct() {
   parent::__construct();
   $this->crea_dati_inserimento();
}
public function crea_dati_inserimento(){
   for($i=0;$i<$this->num_rows;$i++){
      foreach ($this->model as $items){
         $this->data[$i][$items]=random_string('alnum',rand(5,20));
      }
   }
}

public function carica_dati_one_row(){
   set_time_limit(0);
   $this->benchmark->mark('code_start');


   foreach ($this->data as $k=>$v){
      $this->db->insert('table1',$v);
   }
  
   /**
    * Inserimento batch
    */
   /*
   $a=array_chunk($this->data,250);
   foreach ($a as $items){
      $this->db->insert_batch('table1',$items);
   }*/

  
  
   $this->benchmark->mark('code_end');

   echo $this->benchmark->elapsed_time('code_start', 'code_end');
}

[/PHP]
Effettua tutta la porzione di codice che serve alla fine dividi l'array in pacchetti da 200/250 e inserisci/aggiorni in batch.

Credo sia abbastanza chiaro il concetto.!

Qui il codice (CI) per la verifica dei tempi, crea una tabella con id,text1,text2,text3,text4 e aggiungi nell'autoload l'helper string.
PHP:
private $num_rows=25000;
private $model=['text1','text2','text3','text4'];
private $data=[];
public function __construct() {
   parent::__construct();
   $this->crea_dati_inserimento();
}
public function crea_dati_inserimento(){
   for($i=0;$i<$this->num_rows;$i++){
      foreach ($this->model as $items){
         $this->data[$i][$items]=random_string('alnum',rand(5,20));
      }
   }
}

public function carica_dati_one_row(){
   set_time_limit(0);
   $this->benchmark->mark('code_start');


   foreach ($this->data as $k=>$v){
      $this->db->insert('table1',$v);
   }
  
   /**
    * Inserimento batch
    */
   /*
   $a=array_chunk($this->data,250);
   foreach ($a as $items){
      $this->db->insert_batch('table1',$items);
   }*/

  
  
   $this->benchmark->mark('code_end');

   echo $this->benchmark->elapsed_time('code_start', 'code_end');
}
[/QUOTE]
Semplicemente perfetto !!
 

Discussioni simili