web-dev-qa-db-ja.com

psycopg2で複数のPostgresデータベースを操作する方法

2つの異なるサーバーに2つの異なるPostgresデータベースがあります(1つは実際にはローカルです)。 この質問 と同様に、両方のデータベースを同時に操作したいと思います。しかし、psycopg2を使用してそれを行う方法を理解できません。

だから私はおそらく2つの異なるカーソルが必要だと思っていました:

conn_local = psycopg2.connect(dbname='local_db', Host='localhost')
conn_remote = psycopg2.connect(dbname='remote_db', Host='some.other.server')

curs_local = conn_local.cursor()
curs_remote = conn_remote.cursor()

しかし、それらのデータベースにどのように対処できますか?たとえば、両方のテーブルのデータを結合しようとすると、次のようになります。

curs_local.execute("""
    CREATE TABLE local_db.public.newtable AS
    SELECT remote_db.public.remotetable.rcolumn AS col_from_remote, 
    local_db.public.localtable.lcolumn AS col_from_local
    FROM remote_db.public.remotetable, local_db.public.localtable""")

psycopg2.NotSupportedError: cross-database references are not implemented: "local_db.public.new_table"のスタイルにエラーがあります。 ATTACH TABLEコマンド( ソリューションはこちら で説明)は、Postgres/psycopg2には存在しないようです。

一度に複数のデータベースを操作することは可能ですか? または、最初にremote_dbからlocal_dbにデータをコピー(エクスポート/インポート)する必要がありますか?

7
n1000

はい、複数のデータベースを同時に操作することは可能ですが、間違った場所を探しています。 psycopg2は、PostgreSQLからのデータへのアクセスと操作を単純化するライブラリにすぎませんが、psqlで実行できることをはるかに超えるものではありません。 Foreign Data Wrappers を使用して、データベースレベルで解決できることを探しています。

これはスキーマ定義ではより複雑になりますが、ホストsome.other.serverデータベースremote_dbのリモートテーブルを、データベースlocal_dblocalhostにあるかのように見せることができます。ラッパーを接続する方法の簡単な例:

CREATE EXTENSION postgres_fdw;
CREATE SERVER some_remote_server 
  FOREIGN DATA WRAPPER postgres_fdw 
  OPTIONS (Host 'some.remote.server', port '5432', dbname 'remote_db');
CREATE USER MAPPING FOR local_user 
  SERVER some_remote_server 
  OPTIONS (user 'remote_user', password 'remote_user_password');
CREATE FOREIGN TABLE local_table_name (id int, value int) 
  SERVER some_remote_server 
  OPTIONS ( schema_name 'remote_schema_name', table_name 'remote_table_name');

今ローカルで実行することができます

SELECT * from local_table_name

クエリはリモートホストに対して実行されます。言うまでもなく、これには2つのサーバー間の接続が必要です。

同様に、本当に必要な場合は、localhostに対して「リモート」サーバーを作成し、クロスデータベースクエリ用に別のローカルデータベースを指定できます。汚れていますが、可能です。

@a_horse_with_no_nameが述べたように、これはあまり効率的ではありません。これを頻繁に実行していることに気付いた場合は、最適なパフォーマンスが得られておらず、その時点でデータベースを分離したままにしておくことには十分な理由があります。

7
ats

PostgreSQLは、MySQLがデータベースと呼ぶものを「スキーマ」と呼んでいます。一緒に動作することを意図して、複数のデータベースを作成しないでください。つまり、外部データベースにアクセスする必要がある場合は、PostgreSQL FDWが役立ちます。

3
Evan Carroll

この答え から学んだように、別のアプローチは dblink です。例えば。:

SELECT *
FROM dblink('dbname=mydb', 'select rcol1, rcol2 from remote_db')
  AS t1(rcol1 name, rcol2 text)
1
n1000