All Products
Search
Document Center

AnalyticDB:Access MaxCompute data using ODPS Foreign Tables

Last Updated:Mar 28, 2026

MaxCompute foreign data wrapper (FDW) lets you create foreign tables in AnalyticDB for PostgreSQL and use them to read, query, and write data in MaxCompute — without moving data in advance. It is built on the PostgreSQL FDW framework and exposes MaxCompute data as if it were a local table.

MaxCompute FDW supports three foreign table types:

  • Non-partitioned foreign tables — mapped to non-partitioned MaxCompute tables

  • Lowest-level partitioned foreign tables — mapped to a specific lowest-level partition of a partitioned MaxCompute table

  • Partitioned foreign tables — mapped to an entire partitioned MaxCompute table

Prerequisites

Before you begin, ensure that you have:

  • An AnalyticDB for PostgreSQL instance

  • A MaxCompute project and table to access

  • An Alibaba Cloud AccessKey ID and AccessKey Secret with read (and optionally write) access to the MaxCompute project

Enable MaxCompute FDW

New AnalyticDB for PostgreSQL instances have MaxCompute FDW enabled automatically. Skip this section if you are using a new instance.

For an existing instance, connect to the target database using the privileged database account and run:

CREATE EXTENSION odps_fdw;
GRANT USAGE ON FOREIGN DATA WRAPPER odps_fdw TO PUBLIC;

Set up access to MaxCompute

Setting up access requires three steps:

  1. Create a MaxCompute server to define the connection endpoint.

  2. Create a user mapping to specify the credentials used to authenticate.

  3. Create a foreign table to map to the MaxCompute table.

The following end-to-end example shows all three steps with consistent naming, ready to copy and run.

-- Step 1: Create the MaxCompute server
CREATE SERVER odps_serv
  FOREIGN DATA WRAPPER odps_fdw
  OPTIONS (
    tunnel_endpoint '<odps-tunnel-endpoint>'  -- Tunnel endpoint (recommended)
  );

-- Step 2: Create a user mapping
CREATE USER MAPPING FOR CURRENT_USER
  SERVER odps_serv
  OPTIONS (
    id  '<your-access-key-id>',      -- AccessKey ID
    key '<your-access-key-secret>'   -- AccessKey Secret
  );

-- Step 3: Create a foreign table (non-partitioned example)
CREATE FOREIGN TABLE IF NOT EXISTS odps_lineitem (
    l_orderkey      bigint,
    l_partkey       bigint,
    l_suppkey       bigint,
    l_linenumber    bigint,
    l_quantity      double precision,
    l_extendedprice double precision,
    l_discount      double precision,
    l_tax           double precision,
    l_returnflag    char(1),
    l_linestatus    char(1),
    l_shipdate      date,
    l_commitdate    date,
    l_receiptdate   date,
    l_shipinstruct  char(25),
    l_shipmode      char(10),
    l_comment       varchar(44)
)
  SERVER odps_serv
  OPTIONS (
    project 'odps_fdw',    -- MaxCompute project name
    table   'lineitem_big' -- MaxCompute table name
  );

Replace the placeholder values:

PlaceholderDescriptionExample
<odps-tunnel-endpoint>MaxCompute Tunnel endpointdt.cn-hangzhou.maxcompute.aliyun-inc.com
<your-access-key-id>AccessKey IDLTAI5tXxx
<your-access-key-secret>AccessKey SecretxXxXxXx

Step 1: Create a MaxCompute server

The server object tells AnalyticDB for PostgreSQL how to reach MaxCompute. Specify at least one endpoint option.

OptionRequiredDescription
tunnel_endpointNo (recommended)Endpoint of the MaxCompute Tunnel service
odps_endpointNoEndpoint of the MaxCompute service

If you specify both options, tunnel_endpoint takes precedence. If you specify only odps_endpoint, AnalyticDB for PostgreSQL routes requests to the corresponding Tunnel endpoint automatically.

We recommend that you use the MaxCompute Tunnel endpoint in the Alibaba Cloud classic network or a virtual private cloud (VPC). If you use a VPC endpoint, make sure that the AnalyticDB for PostgreSQL instance and the MaxCompute project reside in the same zone. Accessing MaxCompute data over the Internet via the Tunnel endpoint costs USD 0.1166 per GB.

For the full list of MaxCompute endpoints, see Endpoints.

Step 2: Create a user mapping

The user mapping binds a database user to credentials for accessing the MaxCompute server.

CREATE USER MAPPING FOR { username | USER | CURRENT_USER | PUBLIC }
  SERVER odps_serv
  OPTIONS (
    id  '<odps-access-key-id>',
    key '<odps-access-key-secret>'
  );

Specify who the mapping applies to:

  • username — a specific existing database account

  • CURRENT_USER or USER — the currently connected user

  • PUBLIC — all database accounts

OptionRequiredDescription
idYesAccessKey ID
keyYesAccessKey Secret

Step 3: Create a MaxCompute foreign table

Foreign tables map directly to MaxCompute tables. The project and table options are always required. The partition option is used only for lowest-level partitioned foreign tables.

OptionRequiredDescription
projectYesName of the MaxCompute project. A project is the basic organizational unit in MaxCompute, similar to a database or schema. See Project.
tableYesName of the MaxCompute table. See Table.
partitionNoFull path of the lowest-level partition, in key=value format. Used only for lowest-level partitioned foreign tables.

Non-partitioned foreign tables

A non-partitioned foreign table maps to a non-partitioned MaxCompute table. Set project and table; omit partition.

CREATE FOREIGN TABLE odps_lineitem (
    l_orderkey      bigint,
    l_partkey       bigint,
    l_suppkey       bigint,
    l_linenumber    bigint,
    l_quantity      double precision,
    l_extendedprice double precision,
    l_discount      double precision,
    l_tax           double precision,
    l_returnflag    char(1),
    l_linestatus    char(1),
    l_shipdate      date,
    l_commitdate    date,
    l_receiptdate   date,
    l_shipinstruct  char(25),
    l_shipmode      char(10),
    l_comment       varchar(44)
) SERVER odps_serv
  OPTIONS (
    project 'odps_fdw',
    table   'lineitem_big'
  );

Lowest-level partitioned foreign tables

A lowest-level partitioned foreign table maps to one specific partition of a partitioned MaxCompute table. Set the partition option to the full path of the target partition in key=value format, with no spaces.

The following example maps to the hangzhou subpartition under the 20170601 partition of a two-level partitioned MaxCompute table:

-- The MaxCompute table src is partitioned by pt (level 1) and region (level 2).
CREATE FOREIGN TABLE odps_src_20170601_hangzhou (
    key   text,
    value bigint
) SERVER odps_serv
  OPTIONS (
    project   'odps_fdw',
    table     'src',
    partition 'pt=20170601,region=hangzhou'  -- Full path of the lowest-level partition
  );
ODPS partition

Rules for the partition option:

  • Use key=value format with no spaces.

  • For multi-level partitions, separate pairs with commas: pt=20170601,region=hangzhou.

  • The path must be the full path to the lowest-level partition. Partial paths (e.g., pt=20170601 or region=hangzhou alone) are not valid.

Partitioned foreign tables

A partitioned foreign table maps to an entire partitioned MaxCompute table and mirrors its partition structure inside AnalyticDB for PostgreSQL. Use PARTITION BY LIST to define partitions.

The following example creates a partitioned foreign table for the src MaxCompute table, which has two partition levels (pt and region):

CREATE FOREIGN TABLE odps_src (
    key    text,
    value  bigint,
    pt     text,    -- Level-1 partition key (must be appended after data columns)
    region text     -- Level-2 partition key (must be appended after data columns)
) SERVER odps_serv
  OPTIONS (
    project 'odps_fdw',
    table   'src'
  )
  PARTITION BY LIST (pt)
  SUBPARTITION BY LIST (region)
      SUBPARTITION TEMPLATE (
          SUBPARTITION hangzhou VALUES ('hangzhou'),
          SUBPARTITION shanghai VALUES ('shanghai')
      )
  ( PARTITION "20170601" VALUES ('20170601'),
    PARTITION "20170602" VALUES ('20170602') );

Requirements that differ from partitioned tables in MaxCompute:

  • Append partition key columns after all data columns. For multi-level partitions, the order must match the MaxCompute partition hierarchy.

  • Use the LIST partitioning method.

  • Do not set the partition option. If set, the foreign table maps to a specific lowest-level partition instead of the whole table.

If a partition or subpartition in the foreign table has no matching partition in MaxCompute, a warning appears when you query the table. Delete the unmatched partition or subpartition from the foreign table to clear the warning. See Delete partitions or subpartitions from a partitioned foreign table.
Unmatched partition warning

Manage partitions in a partitioned foreign table

The following examples use the odps_src partitioned foreign table created above.

Add partitions or subpartitions

Add a partition — subpartitions are created automatically based on the subpartition template:

alter table odps_src add partition "20170603" values(20170603);
Add partition

Add a subpartition to an existing partition:

alter table odps_src alter partition "20170603" add partition "nanjing" values('nanjing');
Add subpartition

Delete partitions or subpartitions from a partitioned foreign table

Delete a partition — all cascaded subpartitions are also deleted:

alter table odps_src drop partition "20170602";
Delete partition

Delete a single subpartition:

alter table odps_src alter partition "20170601" drop partition "hangzhou";
Delete subpartition

Data type mappings

Use the following mappings when defining column types in your foreign table. AnalyticDB for PostgreSQL does not support the STRUCT, MAP, or general ARRAY types from MaxCompute. ARRAY types are also not supported when writing data back to MaxCompute.

MaxCompute typeAnalyticDB for PostgreSQL type
BOOLEANbool
TINYINTint2
SMALLINTint2
INTEGERint4
BIGINTint8
FLOATfloat4
DOUBLEfloat8
DECIMALnumeric
BINARYbytea
VARCHAR(n)varchar(n)
CHAR(n)char(n)
STRINGtext
DATEdate
DATETIMEtimestamp
TIMESTAMPtimestamp
ARRAY\<SMALLINT/INT/BIGINT/BOOLEAN/FLOAT/DOUBLE/TEXT/VARCHAR/TIMESTAMP\> (not supported for writing to MaxCompute foreign tables)int2, int4, int8, boolean, float4, float8, text, varchar, timestamp

Query and move data

Foreign tables support the same SQL syntax as local tables. The following examples cover common data workflows.

Query a MaxCompute foreign table

Run foreign scans directly on a foreign table just as you would on a local table. The following example runs a TPC-H Q1 aggregation query on odps_lineitem:

-- TPC-H Q1
select
    l_returnflag,
    l_linestatus,
    sum(l_quantity)                                       as sum_qty,
    sum(l_extendedprice)                                  as sum_base_price,
    sum(l_extendedprice * (1 - l_discount))               as sum_disc_price,
    sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge,
    avg(l_quantity)                                       as avg_qty,
    avg(l_extendedprice)                                  as avg_price,
    avg(l_discount)                                       as avg_disc,
    count(*)                                              as count_order
from
    odps_lineitem
where
    l_shipdate <= date '1998-12-01' - interval '88' day
group by
    l_returnflag,
    l_linestatus
order by
    l_returnflag,
    l_linestatus;

Import MaxCompute data into a local table

For large datasets or repeated queries, import data from a foreign table into a local table to avoid repeatedly scanning MaxCompute over the network.

Use INSERT INTO to import into an existing table:

INSERT INTO <destination-table> SELECT * FROM <foreign-table>;

Or use CREATE TABLE AS to create and populate a new table in one step:

CREATE TABLE <destination-table> AS SELECT * FROM <foreign-table>;

Example 1: Import odps_lineitem into an append-optimized column store (AOCS) table:

-- Create a local AOCS table
CREATE TABLE aocs_lineitem (
    l_orderkey      bigint,
    l_partkey       bigint,
    l_suppkey       bigint,
    l_linenumber    bigint,
    l_quantity      double precision,
    l_extendedprice double precision,
    l_discount      double precision,
    l_tax           double precision,
    l_returnflag    char(1),
    l_linestatus    char(1),
    l_shipdate      date,
    l_commitdate    date,
    l_receiptdate   date,
    l_shipinstruct  char(25),
    l_shipmode      char(10),
    l_comment       varchar(44)
) WITH (APPENDONLY=TRUE, ORIENTATION=COLUMN, COMPRESSTYPE=ZSTD, COMPRESSLEVEL=5)
  DISTRIBUTED BY (l_orderkey);

-- Import data from the foreign table
INSERT INTO aocs_lineitem SELECT * FROM odps_lineitem;

Example 2: Import odps_lineitem into a heap table using CREATE TABLE AS:

CREATE TABLE heap_lineitem AS
    SELECT * FROM odps_lineitem
    DISTRIBUTED BY (l_orderkey);

Join a foreign table with a local table

Query a foreign table and a local table together in a single SQL statement. The following example runs a TPC-H Q19 join query between the odps_part foreign table and the local aocs_lineitem table:

-- TPC-H Q19
select
    sum(l_extendedprice * (1 - l_discount)) as revenue
from
    aocs_lineitem,   -- local AOCS table
    odps_part        -- MaxCompute foreign table
where
    (
        p_partkey = l_partkey
        and p_brand = 'Brand#32'
        and p_container in ('SM CASE', 'SM BOX', 'SM PACK', 'SM PKG')
        and l_quantity >= 8 and l_quantity <= 8 + 10
        and p_size between 1 and 5
        and l_shipmode in ('AIR', 'AIR REG')
        and l_shipinstruct = 'DELIVER IN PERSON'
    )
    or
    (
        p_partkey = l_partkey
        and p_brand = 'Brand#41'
        and p_container in ('MED BAG', 'MED BOX', 'MED PKG', 'MED PACK')
        and l_quantity >= 15 and l_quantity <= 15 + 10
        and p_size between 1 and 10
        and l_shipmode in ('AIR', 'AIR REG')
        and l_shipinstruct = 'DELIVER IN PERSON'
    )
    or
    (
        p_partkey = l_partkey
        and p_brand = 'Brand#44'
        and p_container in ('LG CASE', 'LG BOX', 'LG PACK', 'LG PKG')
        and l_quantity >= 22 and l_quantity <= 22 + 10
        and p_size between 1 and 15
        and l_shipmode in ('AIR', 'AIR REG')
        and l_shipinstruct = 'DELIVER IN PERSON'
    );

Write data from AnalyticDB for PostgreSQL to MaxCompute

Use INSERT INTO to write data from a local table back to a MaxCompute foreign table:

INSERT INTO odps_lineitem SELECT * FROM heap_lineitem;
ARRAY column types are not supported when writing data to MaxCompute foreign tables.

Limits

MaxCompute FDW synchronizes data via MaxCompute Tunnel. Synchronization performance is subject to server resources and the outbound network bandwidth of MaxCompute Tunnel. Keep the following limits in mind:

  • If your AnalyticDB for PostgreSQL database uses only foreign tables (no local tables), it can contain at most 5 foreign tables.

  • For large foreign tables, import the data into local tables first. Join the imported local data with smaller foreign tables rather than scanning large foreign tables repeatedly to improve synchronization performance.

Troubleshooting

For common errors that occur when using MaxCompute foreign tables, see Tunnel common errors.

What's next