views:

926

answers:

5

I need to copy from a remote postgres server to a local one. I cannot use any ETL tools; it must be done using Perl with DBI. This data will be large so I don't want to use "select from source" and "insert into local". I was looking to use COPY to create a file but this file will be created on the remote server. I can't do that either. I want to use \COPY instead.

How can I use DBI to execute a "\copy from remote table" command and create a local file using DBI in Perl.

Thanks

+2  A: 

You definitely want to use the "copy from" and "copy to" commands to get the data in and out of the databases efficiently. They are orders of magnitude faster than iterating over rows of data. You many also want to turn off the indexes while you're copying data into the target table, then enable them (and let them build) when the copy is complete.

Assuming you are simply connecting to the listener ports of the two databases, simply open a connection to the source database, copy the table(s) to a file, open a connection to the destination database and copy the file back to the target table.

Steve Moyer
Thanks for your answer. I tried using a dblink from my local db into the remote but my connection kept dropping, so the remote admin suggested I used dbi. Is there a parameter that must be set to prevent my connection from being dropped?
A: 

Hmm. \copy to ... is a psql directive, not SQL, so it won't be understood by DBI or by the PostgreSQL server at the other end.

I see that the PostgreSQL's SQL COPY command has FROM STDIN and TO STDOUT options -- but I doubt that DBI has a way to perform the "raw reads" necessary to access the result data. (I'm sure TO STDOUT is how psql internally implements \copy to ....)

So: In your case, I would mount a folder on your source box back to your target box using e.g. samba or nfs, and use plain old COPY TO '/full/path/to/mounted/folder/data.txt' ....

j_random_hacker
Thanks for your answer. I tried using a dblink from my local db into the remote but my connection kept dropping, so the remote admin suggested I used dbi. Is there a parameter that must be set to prevent my connection from being dropped?
Is the connection dropping at random times, or only after long periods of being idle? I don't know of any cures for the former case, but the latter case *might* be caused by some sort of timeout-after-n-seconds-idle parameter, either in the DB or lower in the stack (e.g. an ssh server).
j_random_hacker
only after long periods of being idle.....I tried \copy connecting to remote db in psql, the file is created in my local directory but it's empty. I don't get an error. I know there's data in the table. \copy rmt_table to '/mylocal/file.txt' am i missing something? a switch?. thanks for your help
Sounds like you're hitting some "link idle" timeout, either in PostgreSQL itself or another layer. Not sure why "\copy rmt_table to '/mylocal/file.txt'" fails -- maybe your disk is full? I'd clear some disk space and try it with a small table as a test.
j_random_hacker
I got it to work using \copy (select * from remote_table) to '/local/file.txt' ... then \copy local_table from '/local/file.txt' to load the file into the local db. thanks for all your help
A: 

I got it to work using \copy (select * from remote_table) to '/local/file.txt' ... then \copy local_table from '/local/file.txt' to load the file into the local db. I executed the \copy command from a psql script.

Here's my script

export PGUSER=remoteuser export PGPASSWORD=remotepwd

/opt/PostgreSQL/8.3/bin/psql -h xx.xx.xx -p 5432 -d remotedb -c "\COPY (select * from remote_table where date(reccreationtim e) = date((current_date - interval '4 day'))) TO '/local/copied_from_remote.txt' D ELIMITER '|'"

export PGUSER=localuser export PGPASSWORD=localpwd

/opt/PostgreSQL/8.3/bin/psql -h xx.xx.xx.xx -p 5432 -d localdb -c "\COPY local_table FROM '/local/copied_from_remote.txt' DELIMITER '|'"

+1  A: 

You can do it in perl with DBD::Pg, details can be found here:

http://search.cpan.org/~turnstep/DBD-Pg-2.13.1/Pg.pm#COPY_support

A: 

You could use ~/.pgpass and save yourself the export PGUSER stuff, and keep the password out of the environment... (always a good idea from a security perspective)

Craig