RE: [PHP] a better way to do a data import?
| From: | Bastien Koert | Date: | Mon, 21 Jan 2008 22:18:54 +0000 |
| Subject: | RE: [PHP] a better way to do a data import? | ||
| References: | 1 2 3 | Groups: | php.general |
| Request: | Send a blank email to php-general+get-267792@lists.php.net to get a copy of this message | ||
what about uploading the entire file into a [semi]temp table..then doing cross table comparisons to
load your main table with the data?
bastien> Date: Mon, 21 Jan 2008 13:08:27 -0500> From: blackwaterdev@gmail.com> To:
bastien> php-general@lists.php.net> Subject: Re: [PHP] a better way to do a data import?> > I think
bastien> that's possible, so I'll give it a shot.> > For some reason, even with straight
bastien> inserts my php script is dying around> 180,000 rows. Basically, I took out all the compare/update
bastien> code so now I> grab the row from the db and if there isn't one, do an insert. I've
bastien> wiped> my db so should do straight inserts so I'm not sure what's taking up the>
bastien> memory.> > > > private function processFile($table, $key){> >
bastien> $this->openFileForReading(); //foudn in GLFile class> while (!feof($this->fileHandle))
bastien> {> $file_data = fgets($this->fileHandle);> > $this->insert($table, $key,
bastien> $file_data);> > }> $this->closeFile();> > }> > private function
bastien> insert($table, $key, $data){> if (strlen($data)<10) return false;> >
bastien> $data=$this->db->escape_string($data);> > //this is the data we will use should we need
bastien> to do an insert> $insert_data = str_replace("\"", "'", $data);>
bastien> > //this is a hack we need to change the separator of the file> //we need this because we need
bastien> to put the data into an array and if> //we simply use the comma, then it splits address
bastien> fields> $data = str_replace("\",\"", "~", $data);> $data =
bastien> str_replace("\"","",$data); //let's remove the double quotes>
bastien> $this->setDelimiter("~");> $dataToArray=$this->stringToArray($data);> //set it
bastien> back for other functions> $this->setDelimiter(",");> > //get the id, we trust
bastien> it is the first column> > > $key_data=$dataToArray[0];> > //does the value exist in
bastien> the database already?> $sql="select * from prelim_$table where
bastien> $key='$key_data'";> $handle=$this->db->select($sql);> if
bastien> ($this->db->row_count($handle)>0){> $textData=array();>
bastien> $colsToUpdate="";> $dataRow="";>
bastien> $dataRow=$this->db->fetch_row($handle);> //now that we have the data, let's merge the
bastien> row from the> //file with the column names> >
bastien> $textData=array_combine($this->carrierColumns,> $dataToArray);> //cast some values that are
bastien> strings in the text file> $textData['cars1']=(int) $textData['cars1'];>
bastien> $textData['car_amount']=(int)> $textData['car_amount'];> >
bastien> $textData['total_work']=trim($textData['total_work']);> >
bastien> $textData['business_zip']=trim($textData['business_zip']);> //clean up some
bastien> old db data> $dataRow['rfc_number']=trim($dataRow['rfc_number']);> >
bastien> $dataRow['business_zip']=trim($dataRow['business_zip']);> > > >
bastien> $colsToUpdate=array_diff($textData,$dataRow);> > //if we have columns to update, do it> if
bastien> (count($colsToUpdate)>0){> > $colset="";> foreach ($colsToUpdate as
bastien> $column=>$value){> $colset.="$column='$value',";> }> //strip last
bastien> comma> $colset=substr($colset, 0, -1);> $sql="update prelim_$table set $colset where>
bastien> $key='$key_data'";> $this->db->write($sql);> > }> >
bastien> $dataRow=NULL;> $colsToUpdate=NULL;> $colset=NULL;> $textData=NULL;> }> else{>
bastien> > //insert the row> $sql="insert into prelim_$table values (";>
bastien> $sql.=trim($insert_data);> $sql.=");";> $this->db->write($sql);> }> >
bastien> > > > }> > > On Jan 21, 2008 12:55 PM, Robert Cummings
bastien> <robert@interjinn.com> wrote:> > >> > On Mon, 2008-01-21 at 12:35 -0500,
bastien> blackwater dev wrote:> > > I have a text file that contains 200k rows. These rows are to
bastien> be> > imported> > > into our database. The majority of them will already exists while
bastien> a few> > are> > > new. Here are a few options I've tried:> > >> >
bastien> > I've had php cycle through the file row by row and if the row is there,> > >
bastien> delete it and do a straight insert but that took a while.> > >> > > Now I have php
bastien> get the row from the text file and then to array_combine> > with> > > a default array
bastien> I have in the class so I can have key value pairs. I> > then> > > take that generated
bastien> array and do array_diff to the data array I pulled> > from> > > the db and I then
bastien> have the columns that are different so I do an update> > on> > > only those columns
bastien> for that specific row. This is slow and after about> > > 180,000 rows, php throws a memory
bastien> error. I'm resetting all my vars to> > NULL> > > at each iteration so am not
bastien> sure what's up.> > >> > >> > > Anyone have a better way to do this?
bastien> In MySQL, I could simply a replace> > on> > > each row...but not in postgres.>
bastien> >> > Does Postgres support any method of temporarily disabling keys/indexing?> >
bastien> Indexing is what causes the inserts to take a while. MySQL can optimize> > an import by
bastien> locking the table and allowing the keys/indexes to be> > temporarily disabled. You'll see
bastien> the following lines in recent MySQL> > database dumps surrounding the inserts:> >>
bastien> > /*!40000 ALTER TABLE
xxx DISABLE KEYS */;> > INSERT
bastien> ...> > INSERT ...> > /*!40000 ALTER TABLE xxx ENABLE
bastien> KEYS */;> >> > Cheers,> > Rob.> > --> >
bastien> ............................................................> > SwarmBuy.com -
bastien> http://www.swarmbuy.com> >> > Leveraging the buying
bastien> power of the masses!> > ...........................................................>
bastien> >> >
_________________________________________________________________