Starting from V3.2, Hologres can access Paimon tables through a Data Lake Formation (DLF) catalog. Map a DLF catalog to an External Database or a foreign server to query, write to, and time-travel Paimon tables in SQL—without migrating data into Hologres native storage.
Usage notes
Capability by version:
|
Capability |
Minimum version |
|
Read Paimon tables via External Database |
V3.2 |
|
Time Travel, branch queries, and data mirroring |
V3.2 |
|
Dynamic Table (full, incremental, and auto refresh) |
V3.2 |
|
Write to Paimon primary key tables ( |
V4.0 |
|
Read data from tags corresponding to expired snapshots |
V3.2.6 / V4.0.6 |
|
Read and write Paimon Blob data (maps to the |
V4.2 |
|
Read the Bitmap File Index (index format V2) on Paimon tables directly, to skip irrelevant rows in equality (=) and IN queries. Enabled by default. See Accelerate queries with the Bitmap File Index. |
V5.0 |
Key exclusions:
-
DLF services must be in the same region as the Hologres instance.
-
Time Travel, branch queries, and data mirroring are only available for foreign tables mapped via an External Database—not for foreign tables created via a foreign server.
-
Time Travel is not supported on tables with schema evolution, or in Dynamic Table queries.
-
Data mirroring does not support Paimon primary key tables.
-
Read-only replica instances do not support data lake acceleration.
-
Writing to Paimon dynamic bucketing tables (created with
bucket = -1or without abucketparameter) is not supported. -
TRUNCATEis not supported on foreign tables. UseINSERT OVERWRITEwith empty data instead. -
UPDATEandDELETEare only supported on primary key tables where the Merge Engine isdeduplicateorpartial-update. Updating primary key columns is not supported. -
For
partial-updatetables, enable thepartial-update.remove-record-on-deleteproperty before runningDELETE. -
Foreign tables do not support mixed DML transactions. Only single DML operations use a two-phase commit protocol to guarantee atomicity.
-
Default partitioned data (empty or NULL partition values) cannot be read from Paimon.
-
The Bitmap File Index applies only to equality (
=) andINpredicates. Range predicates (>,<,BETWEEN) and pattern matching (LIKE) do not use it. -
A column gets a Bitmap File Index only if you declare it in the
file-index.bitmap.columnstable property. Columns that are not declared get no bitmap acceleration. -
The
FLOAT,DOUBLE, andDECIMALdata types cannot be indexed with a Bitmap File Index.
Prerequisites
Make sure you have:
-
Activated DLF service V2.5 or later and created a DLF catalog. See Authorize and activate DLF and Data catalog.
For DLF service endpoints, see Service endpoints.
-
A Hologres instance with the data lake acceleration service enabled. See Purchase a Hologres instance and Data lake acceleration for OSS access using DLF.
Starting from V5.0, Hologres enables data lake acceleration by default. To turn it off, use the Hologres console.
Connect to a DLF catalog
Hologres supports two approaches to connect to a DLF catalog:
|
Approach |
Best for |
|
External Database (recommended) |
Most use cases. Supports Time Travel, branch queries, and data mirroring. Requires V3.2+. |
|
Foreign server (legacy) |
DLF 1.0 environments or workloads that don't require Time Travel. |
Use an External Database (recommended)
An External Database maps a DLF catalog into Hologres so you can query, manage, and mirror Paimon tables. It supports two authentication modes:
|
Mode |
When to use |
|
SLR mode (default) |
Access the catalog with your current Alibaba Cloud identity. Suitable for single-account setups. |
|
STS mode |
Cross-account access, or when Hologres BASIC accounts need to access the catalog. |
SLR mode
A service-linked role (SLR) lets Hologres access other Alibaba Cloud services on your behalf using your current identity. For instances newly purchased or upgraded to V2.2 or later, the SLR is created automatically.
For instances running earlier than V2.2, create the SLR manually on the RAM Quick Authorization page.
-
Connect to the Hologres instance and create an External Database.
Parameter
Required
Description
catalog_typeYes
Set to
paimon.metastore_typeYes
Set to
dlf-restfor DLF V2.5+.dlf_catalogYes
The name of the DLF catalog to map.
commentNo
A description for the External Database.
CREATE EXTERNAL DATABASE <ext_database_name> WITH catalog_type 'paimon', metastore_type 'dlf-rest', dlf_catalog '<dlf_catalog_name>', comment 'dlf catalog'; -
List the schemas and tables in the External Database.
-- List schemas SELECT * FROM hologres.hg_external_schemas('<ext_database_name>'); -- List tables in a schema SELECT * FROM hologres.hg_external_tables('<ext_database_name>', '<ext_schema_name>'); -
Query table data.
SELECT * FROM <ext_database_name>.<ext_schema_name>.<ext_table_name>;
STS mode
Security Token Service (STS) issues temporary credentials with limited scope and validity. Use STS mode for cross-account access or when BASIC accounts need to access the catalog.
-
In the RAM console, create a RAM role and grant it the
AliyunDLFFullAccessorAliyunDLFReadOnlyAccesspermission. See Create a RAM role and grant permissions. -
Update the trust policy of the RAM role to allow Hologres to assume it. See Modify the trust policy of a RAM role.
{ "Statement": [ { "Action": "sts:AssumeRole", "Effect": "Allow", "Principal": { "Service": [ "hologres.aliyuncs.com" ] } } ], "Version": "1" } -
In the Data Lake Formation console, grant the RAM role access to the target databases and tables in the DLF catalog.
-
Create an External Database in Hologres, specifying the RAM role as the authentication policy.
Parameter
Required
Description
catalog_typeYes
Set to
paimon.metastore_typeYes
Set to
dlf-restfor DLF V2.5+.dlf_catalogYes
The name of the DLF catalog to map.
rolearnYes
The ARN of the RAM role to assume. Format:
acs:ram::<account_id>:role/<role_name>.commentNo
A description for the External Database.
CREATE EXTERNAL DATABASE <ext_database_name> WITH catalog_type 'paimon', metastore_type 'dlf-rest', dlf_catalog '<dlf_catalog_name>', rolearn 'acs:ram::<account_id>:role/<role_name>', comment 'dlf catalog'; -
Create a USER MAPPING to associate the RAM user or BASIC account with the RAM role.
- For USER MAPPING syntax, see CREATE USER MAPPING. - To create a RAM user, see Create a RAM user. - To create a BASIC account, see User management.
CREATE USER MAPPING FOR "<ram_user_or_basic_account>" EXTERNAL DATABASE <ext_database_name> OPTIONS ( rolearn 'acs:ram::<account_id>:role/<role_name>' ); -
Log in to the Hologres console as the RAM user, or reconnect to the Hologres instance as the BASIC account, then run queries.
SELECT * FROM <ext_database_name>.<ext_schema_name>.<ext_table_name>;
More operations:
-
External Database: EXTERNAL DATABASE
-
External Schema: EXTERNAL SCHEMA
-
External Table: EXTERNAL TABLE
Use a foreign server (legacy)
The foreign server approach does not support Time Travel, branch queries, or data mirroring. Use an External Database for those features.
Step 1: Create a foreign server.
For DLF V2.5 and later:
CREATE SERVER IF NOT EXISTS <server_name> FOREIGN DATA WRAPPER dlf_fdw OPTIONS (
catalog_type 'paimon',
metastore_type 'dlf-rest',
dlf_catalog '<dlf_catalog_name>'
);
|
Parameter |
Required |
Description |
|
|
Yes |
Set to |
|
|
Yes |
Set to |
|
|
Yes |
The name of the DLF catalog to map. |
For DLF V1.0:
CREATE SERVER IF NOT EXISTS <server_name> FOREIGN DATA WRAPPER dlf_fdw OPTIONS (
dlf_region '',
dlf_endpoint 'dlf-share.<region>.aliyuncs.com',
oss_endpoint 'oss-<region_id>-internal.aliyuncs.com',
dlf_catalog '<dlf_catalog_name>'
);
|
Parameter |
Required |
Description |
|
|
Yes |
The region ID of the DLF service. |
|
|
Yes |
The DLF service endpoint. Format: |
|
|
Yes |
The OSS internal endpoint. Format: |
|
|
Yes |
The name of the DLF catalog to map. |
For more foreign server operations, see More foreign server operations.
Step 2: Create foreign tables.
Use IMPORT FOREIGN SCHEMA to import all tables in a DLF database:
-- Import all tables
IMPORT FOREIGN SCHEMA <dlf_db_name>
FROM SERVER <server_name>
INTO <holo_schema_name>
OPTIONS (if_table_exist 'update');
-- Import specific tables
IMPORT FOREIGN SCHEMA <dlf_db_name>
LIMIT TO (<table_name>[, ...])
FROM SERVER <server_name>
INTO <holo_schema_name>
OPTIONS (if_table_exist 'update');
Or create a single foreign table with CREATE FOREIGN TABLE:
CREATE FOREIGN TABLE <foreign_table_name>
(
<column_name> <data_type>
[, ...]
)
SERVER <server_name>
OPTIONS
(
schema_name '<dlf_db_name>',
table_name '<dlf_table_name>'
);
For syntax details, see IMPORT FOREIGN SCHEMA and CREATE FOREIGN TABLE.
Read Paimon data
Collect statistics for query optimization
Run ANALYZE or AUTO ANALYZE to collect table statistics. The query optimizer uses these statistics to build optimal query plans.
-- Collect statistics for all columns
ANALYZE <ext_database_name>.<ext_schema_name>.<ext_table_name>;
-- Collect statistics for specific columns (more accurate; use for filter columns)
ANALYZE <ext_database_name>.<ext_schema_name>.<ext_table_name>(<col_name>[, <col_name>]);
-- Enable AUTO ANALYZE for an External Database
ALTER EXTERNAL DATABASE <ext_database_name> WITH enable_auto_analyze 'true';
For more details, see ANALYZE and AUTO ANALYZE.
Query with Time Travel
Starting from V3.2, Hologres supports querying historical snapshots of Paimon tables by timestamp, version (snapshot ID), or tag.
Time Travel is only supported for foreign tables mapped via an External Database. It is not supported on tables with schema evolution or in Dynamic Table queries.
List available snapshots:
SELECT * FROM hologres.hg_list_snapshots('<ext_database_name>.<ext_schema_name>.<ext_table_name>');
The snapshots table returns the following fields:
|
Field |
Type |
Description |
|
|
TEXT |
Branch name |
|
|
TEXT |
Snapshot ID |
|
|
TEXT |
Schema ID |
|
|
TEXT |
Commit type |
|
|
TIMESTAMPTZ |
Commit time |
|
|
TEXT (JSON) |
Remaining Paimon snapshot properties |
You can also query the Paimon Snapshots system table using the hg_list_versions function. For Paimon tables, Version corresponds to Snapshot ID.
SELECT * FROM hologres.hg_list_versions('<ext_database_name>.<ext_schema_name>.<ext_table_name>');
List available tags:
SELECT * FROM hologres.hg_list_tags('<ext_database_name>.<ext_schema_name>.<ext_table_name>');
|
Field |
Type |
Description |
|
|
TEXT |
Branch name |
|
|
TEXT |
Tag name |
|
|
TEXT |
Snapshot ID |
|
|
TEXT |
Schema ID |
|
|
TIMESTAMPTZ |
Commit time |
|
|
TEXT (JSON) |
Remaining Paimon tag properties |
Query by timestamp:
SELECT * FROM <ext_database_name>.<ext_schema_name>.<ext_table_name>
FOR TIMESTAMP AS OF '<timestamp>';
Query by version (snapshot ID):
SELECT * FROM '<ext_database_name>.<ext_schema_name>.<ext_table_name>'
FOR VERSION AS OF '<version>';
Query by tag:
SELECT * FROM '<ext_database_name>.<ext_schema_name>.<ext_table_name>'
FOR TAG AS OF '<tag>';
Hologres V3.2.6 and V4.0.6 and later support reading data from tags that correspond to expired Paimon snapshots.
For more information on Paimon system tables, see Paimon system tables.
Query Paimon branches
Starting from V3.2, Hologres can query data from a specific Paimon branch, including historical snapshots within that branch.
List available branches:
SELECT * FROM hologres.hg_list_branches('<ext_database_name>.<ext_schema_name>.<ext_table_name>');
|
Field |
Type |
Description |
|
|
TEXT |
Branch name |
|
|
TIMESTAMPTZ |
Branch creation time |
|
|
TEXT (JSON) |
Remaining Paimon branch properties |
Query the current data of a branch:
SELECT * FROM '<ext_database_name>.<ext_schema_name>.<ext_table_name>'
FOR branch AS OF '<branch_name>';
If scan.fallback-branch is set on the Paimon table, Hologres automatically reads missing partitions from the fallback branch. See Manage branches.
Query historical snapshots within a branch:
-- By timestamp
SELECT * FROM '<ext_database_name>.<ext_schema_name>.<ext_table_name>'
FOR branch AS OF '<branch_name>' TIMESTAMP AS OF '<timestamp>';
-- By tag
SELECT * FROM '<ext_database_name>.<ext_schema_name>.<ext_table_name>'
FOR branch AS OF '<branch_name>' TAG AS '<tag_name>';
Accelerate queries with lake table mirroring
Starting from V3.2, Hologres supports lake table mirroring, which syncs Paimon table metadata and data into Hologres in near-real-time or at scheduled intervals. Mirrored data is served from Hologres storage, significantly reducing query latency. Full table mirroring and partial mirroring of partitioned tables are both supported.
Lake table mirroring does not support Paimon primary key tables.
For setup details, see Lake table mirroring.
Accelerate queries with the Bitmap File Index
Starting from V5.0, Hologres reads the Bitmap File Index (index format V2) on Paimon tables directly. When you filter an indexed column with an equality (=) or IN predicate, the Hologres reader uses the bitmap to locate matching rows and skip irrelevant rows. This cuts the amount of data scanned and speeds up point queries and multi-value queries on lake tables. The capability is enabled by default.
file-index.bitmap.columns is a Paimon table property. It controls the file-level bitmap index stored next to the data files in the lake, and Hologres pushes filters down to that index when it reads the lake table directly. Do not confuse it with data_mirroring_bitmap_columns, which builds a bitmap index on the mirrored table inside Hologres. See Lake table mirroring.
How it works and when it applies:
-
Paimon writers generate the index. Flink, Spark, and other engines can write it, and Hologres also generates it automatically when you run
INSERTagainst a Paimon foreign table—as long asfile-index.bitmap.columnsis declared on the table. -
The index is stored per data file. Each data file gets a companion
.indexfile whose name is prefixed with the data file name. -
The Hologres reader detects the index format version automatically, and both formats can coexist in the same table: index format V2 uses the V2 parser, index format V1 keeps using the V1 parser. Existing queries are unaffected.
-
Supported index column types include fixed-length types (
SMALLINT,INT,BIGINT,DATE,TIME,TIMESTAMP, and so on) and variable-length types (STRINGorTEXT).FLOAT,DOUBLE, andDECIMALare not supported. -
Only equality (
=) andINpredicates benefit. Range predicates,LIKE, and other predicates do not use the bitmap index.
Steps:
-
Declare the bitmap index columns when you create the table.
-- Create a Paimon foreign table and declare the bitmap index columns CREATE EXTERNAL TABLE EXT_DATABASE_NAME.EXT_SCHEMA_NAME.EXT_TABLE_NAME ( id INT, c_id INT, c_name TEXT ) WITH ( "table_format" = 'paimon', "file_format" = 'parquet', -- Both Parquet and ORC support reading the Bitmap File Index "bucket" = '4', "bucket-key" = 'id', "file-index.bitmap.columns" = 'c_id,c_name' -- Columns to index, separated by commas );NoteTo downgrade a specific column to index format V1, set
"file-index.bitmap.<COLUMN_NAME>.version" = '1'for that column. The default is index format V2. -
Verify that the Bitmap File Index switches are enabled. Hologres turns the following switches on by default starting from V5.0. To confirm their state or turn them on manually, run:
-- Global flags that control reading the Bitmap File Index SELECT hg_admin_command('set_global_flag','enable_paimon_bitmap_index=true'); -- Master switch SELECT hg_admin_command('set_global_flag','enable_push_bitmap_to_fse_parquet_reader=true'); -- Pushdown in the Parquet reader SELECT hg_admin_command('set_global_flag','enable_push_bitmap_to_fse_orc_reader=true'); -- Pushdown in the ORC reader -
Run an equality or
INquery, then confirm that the index took effect withEXPLAIN (ANALYZE).-- Query and verify EXPLAIN (ANALYZE) SELECT count(*) FROM EXT_DATABASE_NAME.EXT_SCHEMA_NAME.EXT_TABLE_NAME WHERE c_id = 1;In the query plan, the bottom-level
Seq Scannode reportsbitmap_used=N, where N is the number of predicates served by the bitmap index.scan_rowsconverges to the number of matching rows instead of the full table row count. Both signals mean the index took effect. Example output:-> Seq Scan on EXT_TABLE_NAME (cost=0.00..5.03 rows=1000 width=1) Filter: (c_id = 1) Engine: FSE Foreign Table Type: DLF [id=1 split_count=1 rows=4(4/4/4) scan_rows=4(4/4/4) bitmap_used=1]
The Bitmap File Index takes effect per data file. For the best speedup, keep the values of your filter columns concentrated in as few data files as possible. On bucketed tables, the index applies independently within the data files of each bucket.
Use Dynamic Table for continuous refresh
A Dynamic Table automatically processes and stores aggregated results from one or more Paimon foreign tables, with built-in refresh strategies. MaxCompute foreign tables and DLF foreign tables have been supported as base tables since V3.0.
Dynamic Table does not support Time Travel queries on Paimon tables or branches.
Full refresh — replaces all data on each refresh cycle:
CREATE DYNAMIC TABLE paimon_dt_table
WITH (
auto_refresh_mode = 'full',
freshness = '3 minutes'
) AS SELECT * FROM <ext_database_name>.<ext_schema_name>.<ext_table_name>;
Incremental refresh — processes only new or changed data:
CREATE DYNAMIC TABLE paimon_dt_table_incremental
WITH (
auto_refresh_mode = 'incremental',
freshness = '3 minutes'
) AS SELECT * FROM <ext_database_name>.<ext_schema_name>.<ext_table_name>;
Auto refresh — automatically selects full or incremental refresh based on data changes:
CREATE DYNAMIC TABLE paimon_dt_table_auto
WITH (
auto_refresh_mode = 'auto',
freshness = '3 minutes'
) AS SELECT * FROM <ext_database_name>.<ext_schema_name>.<ext_table_name>;
For more details, see Dynamic Table overview.
Write to Paimon tables
Starting from V4.0, Hologres supports writing to Paimon primary key tables via an External Database. Data is shuffled by bucket before writing to reduce small file generation. A memory-based caching mechanism is available for tables that require caching, including:
-
Tables with
Merge Engineset toFirst Row -
Tables that generate a Changelog through the
lookupmechanism -
Tables with
Deletion Vectorenabled
INSERT INTO
The following example creates a Paimon primary key table and inserts rows.
-- Create a Paimon primary key table
CREATE EXTERNAL TABLE <ext_database_name>.<ext_schema_name>.<ext_table_name> (
id BIGINT,
customer_id BIGINT,
item TEXT,
amount FLOAT,
dt TEXT,
PRIMARY KEY (id)
)
WITH (
"table_format" = 'paimon',
"file_format" = 'orc',
"merge-engine" = 'deduplicate', -- Adjust as needed
"bucket" = '4' -- Adjust as needed
);
-- Insert rows
INSERT INTO <ext_database_name>.<ext_schema_name>.<ext_table_name>
(id, customer_id, item, amount, dt)
VALUES
(1, 1001, 'apple', 3.50, '2025-09-10'),
(2, 1002, 'banana', 2.00, '2025-09-10'),
(3, 1003, 'orange', 4.20, '2025-09-11');
INSERT OVERWRITE
The following example creates a partitioned Paimon append-only table and overwrites a partition.
-- Create a partitioned Paimon append-only table
CREATE EXTERNAL TABLE <ext_database_name>.<ext_schema_name>.<ext_table_name> (
id BIGINT,
name TEXT,
amount FLOAT8,
dt TEXT
)
LOGICAL PARTITION BY LIST(dt)
WITH (
"table_format" = 'paimon',
"file_format" = 'parquet',
"merge-engine" = 'deduplicate',
"bucket-key" = 'id',
"bucket" = '2'
);
-- Overwrite data
INSERT OVERWRITE <ext_database_name>.<ext_schema_name>.<ext_table_name>
(id, name, amount, dt)
VALUES
(1, 'Alice', 100.50, '2025-09-01'),
(2, 'Bob', 200.00, '2025-09-01'),
(3, 'Carol', 150.75, '2025-09-02');
UPDATE
UPDATE is supported only on Paimon primary key tables where the Merge Engine is deduplicate or partial-update. Updating primary key columns is not supported.
UPDATE <ext_database_name>.<ext_schema_name>.<ext_table_name>
SET amount = 5
WHERE id = 1;
DELETE
DELETE is supported only on Paimon primary key tables where the Merge Engine is deduplicate or partial-update. For partial-update tables, enable the partial-update.remove-record-on-delete property before running DELETE.
DELETE FROM <ext_database_name>.<ext_schema_name>.<ext_table_name>
WHERE id = 2;