All Products
Search
Document Center

Hologres:Cross-database query (beta)

Last Updated:Mar 26, 2026

Cross-database query lets you read data from Hologres internal tables in other instances and databases — including instances in different regions — without moving the data. It uses the PostgreSQL foreign data wrapper (FDW) mechanism. For more information about FDW, see PostgreSQL FDW documentation.

Limitations

Before you set up cross-database queries, review the following constraints:

  • Requires Hologres V1.1 or later on both the source and destination instances. If your instance is earlier than V1.1, see Common upgrade preparation failure errors or get online support for upgrade assistance. Cross-database queries are supported only between instances of the same major version — for example, a V1.3 instance cannot query a V1.1 instance.

  • Supported source objects: internal tables and partitioned parent tables only. Foreign tables, views, and partitioned child tables are not supported.

  • Supported data types: basic types only. Complex types such as JSON are not supported.

  • Supported operations on foreign tables: SELECT only. UPDATE, DELETE, and TRUNCATE are not supported.

  • Hologres instance IP addresses are not fixed. Do not configure IP address whitelists when using this feature, as the connection may break if the IP address changes.

Supported data types

SupportedNot supported
INTJSON
BIGINTOther complex types
DATE

Prerequisites

Before you begin, ensure that you have:

  • A Hologres instance running V1.1 or later (both local and remote)

  • Superuser access to the local database

  • An Alibaba Cloud AccessKey ID and AccessKey secret for the account that has SELECT permission on the source tables. Get them from the RAM console

Set up cross-database query

Setting up a cross-database query involves four configuration steps, followed by running the query.

Step 1: Create the extension

A superuser must run the following statement once per database to install the FDW extension:

CREATE EXTENSION hologres_fdw;
Note

To uninstall the extension, run DROP EXTENSION hologres_fdw;.

Step 2: Create a server

After the extension is installed, create a server object that points to the remote Hologres instance:

CREATE SERVER <server_name> FOREIGN DATA WRAPPER hologres_fdw OPTIONS (
    host '<endpoint>',
    port '<port>',
    dbname '<dbname>'
);
ParameterDescriptionExample
server_nameA name you assign to the server.holo_fdw_server
hostThe classic network (internal network) endpoint of the remote Hologres instance. Find it on the Instance Configuration tab in the Hologres console.hgpostcn-cn-xxx-cn-hangzhou-internal.hologres.aliyuncs.com
portThe port of the remote Hologres instance. Find it on the Instance Configuration tab in the Hologres console.80
dbnameThe name of the remote database to query.testdb
Note

You can create multiple servers in the same database.

Step 3: Create a user mapping

Create a user mapping to authenticate the cross-database connection. The mapped account must have SELECT permission on the source tables.

CREATE USER MAPPING FOR <account_uid> SERVER <server_name>
OPTIONS (
    access_id '<access_id>',
    access_key '<access_key>'
);
ParameterDescription
account_uidThe local user to map. Use CURRENT_USER for the current session user, or a RAM user in p4_<uid> format.
server_nameThe server name from step 2.
access_idThe AccessKey ID of the account.
access_keyThe AccessKey secret of the account.

Examples:

-- Map the current user.
CREATE USER MAPPING FOR CURRENT_USER SERVER holo_fdw_server OPTIONS (
    access_id 'yourAccessKeyId',
    access_key 'yourAccessKeySecret'
);

-- Map a RAM user.
CREATE USER MAPPING FOR "p4_123xxx" SERVER holo_fdw_server OPTIONS (
    access_id 'yourAccessKeyId',
    access_key 'yourAccessKeySecret'
);

-- Remove a user mapping.
DROP USER MAPPING FOR CURRENT_USER SERVER holo_fdw_server;
DROP USER MAPPING FOR "p4_123xxx" SERVER holo_fdw_server;
Note

You can create multiple user mappings in the same database.

Step 4: Create a foreign table

Use one of the following two methods to create a foreign table. The IMPORT FOREIGN SCHEMA method is simpler and is recommended for most cases.

Method 1 (recommended): IMPORT FOREIGN SCHEMA

IMPORT FOREIGN SCHEMA <holo_remote_schema>
[{ LIMIT TO | EXCEPT } (<remote_table> [, ...])]
FROM SERVER <server_name>
INTO <holo_local_schema>
[OPTIONS (<option> '<value>' [, ...])];
ParameterDescriptionExample
holo_remote_schemaThe schema name in the remote database where the source table resides.remote
remote_tableThe source table name. The foreign table is created with the same name in the local schema.lineitem
server_nameThe server name from step 2.holo_fdw_server
holo_local_schemaThe local schema where the foreign table is created.local

Supported options:

OptionDescriptionDefault
import_collateInclude column collation settings.true
import_defaultInclude column default values.false
import_not_nullInclude NOT NULL constraints.true
Note

Use LIMIT TO to import only the tables you need. Importing the full remote schema can be slow if it contains many tables.

Method 2: CREATE FOREIGN TABLE

CREATE FOREIGN TABLE <local_table> (
    col_name type,
    ...
) SERVER <server_name>
OPTIONS (schema_name '<remote_schema_name>', table_name '<remote_table>');
ParameterDescriptionExample
local_tableThe name of the foreign table to create locally. To place it in a custom schema, use schema.table format.public.lineitem
server_nameThe server name from step 2.holo_fdw_server
remote_schema_nameThe schema name in the remote database.public
remote_tableThe source table name in the remote database.holo_lineitem

Step 5: Query the foreign table

After the foreign table is created, query it directly:

SELECT * FROM <holo_local_table> LIMIT 10;

Step 6 (optional): Import data into a local internal table

If foreign table query performance does not meet your needs, or if you need a local copy of the data, import it into a Hologres internal table:

INSERT INTO <holo_table> SELECT * FROM <holo_local_table>;

Create the target internal table before running this statement. See Manage internal tables for details.

Manage servers and user mappings

List servers

SELECT
    s.srvname AS "Name",
    pg_catalog.pg_get_userbyid(s.srvowner) AS "Owner",
    f.fdwname AS "Foreign-data wrapper",
    pg_catalog.array_to_string(s.srvacl, E'\n') AS "Access privileges",
    s.srvtype AS "Type",
    s.srvversion AS "Version",
    CASE WHEN srvoptions IS NULL THEN
        ''
    ELSE
        '(' || pg_catalog.array_to_string(ARRAY (
                SELECT
                    pg_catalog.quote_ident(option_name) || ' ' || pg_catalog.quote_literal(option_value)
                FROM pg_catalog.pg_options_to_table(srvoptions)), ', ') || ')'
    END AS "FDW options",
    d.description AS "Description"
FROM
    pg_catalog.pg_foreign_server s
    JOIN pg_catalog.pg_foreign_data_wrapper f ON f.oid = s.srvfdw
    LEFT JOIN pg_catalog.pg_description d ON d.classoid = s.tableoid
        AND d.objoid = s.oid
        AND d.objsubid = 0
WHERE
    f.fdwname = 'hologres_fdw';

List user mappings

SELECT
    um.srvname AS "Server",
    um.usename AS "User name",
    CASE WHEN umoptions IS NULL THEN
        ''
    ELSE
        '(' || pg_catalog.array_to_string(ARRAY (
                SELECT
                    pg_catalog.quote_ident(option_name) || ' ' || pg_catalog.quote_literal(option_value)
                FROM pg_catalog.pg_options_to_table(umoptions)), ', ') || ')'
    END AS "FDW options"
FROM
    pg_catalog.pg_user_mappings um
WHERE
    um.srvname != 'query_log_store_server';

Delete a user mapping

DROP USER MAPPING FOR <account_uid> SERVER <server_name>;

Delete a server

Important

Delete all related user mappings and foreign tables before dropping a server.

DROP SERVER <server_name>;

Examples

The following examples use a shared source instance and database. Run all statements in the local database — the one where you perform the cross-database query.

Source instance configuration

ConfigurationValue
Source instance IDhgpostcn-cn-i7mxxxxxxxxx
Source databaseremote_db
Source schemaremote
Non-partitioned tablelineitem
Partitioned parent tableholo_dwd_product_movie_basic_info

DDL for the source Hologres internal table

BEGIN;
CREATE SCHEMA remote;
CREATE TABLE "remote"."lineitem" (
    "l_orderkey"      int8        NOT NULL,
    "l_linenumber"    int8        NOT NULL,
    "l_suppkey"       int8        NOT NULL,
    "l_partkey"       int8        NOT NULL,
    "l_quantity"      int8        NOT NULL,
    "l_extendedprice" int8        NOT NULL,
    "l_discount"      int8        NOT NULL,
    "l_tax"           int8        NOT NULL,
    "l_returnflag"    text        NOT NULL,
    "l_linestatus"    text        NOT NULL,
    "l_shipdate"      timestamptz NOT NULL,
    "l_commitdate"    timestamptz NOT NULL,
    "l_receiptdate"   timestamptz NOT NULL,
    "l_shipinstruct"  text        NOT NULL,
    "l_shipmode"      text        NOT NULL,
    "l_comment"       text        NOT NULL
);
COMMIT;

DDL for the source Hologres partitioned table

BEGIN;
CREATE TABLE "remote"."holo_dwd_product_movie_basic_info" (
    "movie_name"     text,
    "director"       text,
    "scriptwriter"   text,
    "area"           text,
    "actors"         text,
    "type"           text,
    "movie_length"   text,
    "movie_date"     text,
    "movie_language" text,
    "imdb_url"       text,
    "ds"             text
)
PARTITION BY LIST (ds);
COMMIT;

-- Create a partition for '20170122'.
CREATE TABLE IF NOT EXISTS "remote".holo_dwd_product_movie_basic_info_20170122
    PARTITION OF "remote".holo_dwd_product_movie_basic_info
    FOR VALUES IN ('20170122');

Example 1: Query a non-partitioned table

-- Run as a superuser in the local database.

-- Step 1: Install the extension.
CREATE EXTENSION hologres_fdw;

-- Step 2: Create a server pointing to the remote instance.
CREATE SERVER holo_fdw_server FOREIGN DATA WRAPPER hologres_fdw OPTIONS (
    host 'hgpostcn-cn-i7mxxxxxxxxx-cn-hangzhou-internal.hologres.aliyuncs.com',
    port '80',
    dbname 'remote_db'
);

-- Step 3: Create a user mapping for the current user.
CREATE USER MAPPING FOR CURRENT_USER SERVER holo_fdw_server
OPTIONS (access_id 'yourAccessKeyId', access_key 'yourAccessKeySecret');

-- Step 4: Create a local schema and import the foreign table.
CREATE SCHEMA local;

IMPORT FOREIGN SCHEMA remote
LIMIT TO (lineitem)
FROM SERVER holo_fdw_server
INTO local
OPTIONS (import_not_null 'true');

-- Step 5: Query the foreign table.
SELECT * FROM local.lineitem LIMIT 10;

Example 2: Query a partitioned table

-- Run as a superuser in the local database.

CREATE EXTENSION hologres_fdw;

CREATE SERVER holo_fdw_server FOREIGN DATA WRAPPER hologres_fdw OPTIONS (
    host 'hgpostcn-cn-i7mxxxxxxxxx-cn-hangzhou-internal.hologres.aliyuncs.com',
    port '80',
    dbname 'remote_db'
);

CREATE USER MAPPING FOR CURRENT_USER SERVER holo_fdw_server
OPTIONS (access_id 'yourAccessKeyId', access_key 'yourAccessKeySecret');

CREATE SCHEMA local;

-- Import the partitioned parent table (child tables are included automatically).
IMPORT FOREIGN SCHEMA remote
LIMIT TO (holo_dwd_product_movie_basic_info)
FROM SERVER holo_fdw_server
INTO local
OPTIONS (import_not_null 'true');

SELECT * FROM local.holo_dwd_product_movie_basic_info LIMIT 10;

Example 3: Import data from a foreign table into a local internal table

-- Create a local schema.
CREATE SCHEMA local;

-- Create the target internal table.
BEGIN;
CREATE TABLE "local"."dwd_product_movie_basic_info" (
    "movie_name"     text,
    "director"       text,
    "scriptwriter"   text,
    "area"           text,
    "actors"         text,
    "type"           text,
    "movie_length"   text,
    "movie_date"     text,
    "movie_language" text,
    "imdb_url"       text,
    "ds"             text
);
COMMIT;

-- Copy data from the foreign table into the internal table.
INSERT INTO local.dwd_product_movie_basic_info
SELECT * FROM local.holo_dwd_product_movie_basic_info;

Troubleshooting

Error when querying a read-only replica

If you configure a read-only replica instance as the query target, you may see the following error:

internal error: Failed to get available shards for query[xxxxx], please retry later.

Run the following statement in both the primary instance of the read-only replica and the local (initiating) instance:

ALTER DATABASE <database> SET hg_experimental_enable_dml_read_replica=ON;

Use the primary instance as the query target whenever possible.