Spark is the workhorse of the OSS Tables ecosystem. It creates tables, runs batch ETL, and handles complex analytics. But once you start building, you hit the gap between storing the data and getting Spark to query it — and closing that gap takes engineering work.
Metadata management is the classic example. Before Spark can read or write tables in the lake, something has to track which tables exist, what their schemas are, and where the data files live. That something is a catalog service. The traditional answer is to stand up a Hive Metastore backed by a relational database. It works, but it adds operational overhead, and every extra component widens the failure surface.
OSS Tables takes a direct approach. It is natively compatible with the Apache Iceberg REST Catalog protocol, so Spark connects through a standard Iceberg client with no catalog service to deploy. Table creation, queries, writes, and time travel all use standard SQL, and in your code you change a single line of catalog configuration.
In other words: your data already sits on OSS, so you only need to point Spark at OSS Tables to get a complete data warehouse solution.
The following end-to-end example shows how to connect Spark to OSS Tables, create a table, write data, and run a time travel query.
• Spark 3.5 or later is installed, running on Java 11 or later.
• An OSS Tables Table Bucket has been created. If you have not created one, see OSS Tables.
Put the following JAR files in the $SPARK_HOME/jars directory, or pass them with the --jars parameter at startup.
| JAR file | Description |
|---|---|
| iceberg-spark-runtime-3.5_2.12-1.10.1.jar | Iceberg Spark Runtime package, which provides Iceberg's Spark integration. Choose the package that matches your Spark version (for example, Spark 3.5 pairs with iceberg-spark-runtime-3.5_2.12). |
| iceberg-aws-bundle-1.10.1.jar | Iceberg AWS bundle, which provides the S3FileIO implementation and the AWS SDK required for REST Catalog sigv4 signature authentication. Its version must match the Runtime package. |
The Iceberg REST Catalog uses sigv4 signature authentication, and S3FileIO also needs credentials to reach the data plane. We recommend supplying both sets of credentials through environment variables. Set the following variables before you start Spark:
Note
The variable names carry the AWS_ prefix because Iceberg's sigv4 signer and S3FileIO reuse the standard AWS SDK credentials provider chain. The values you supply are your Alibaba Cloud AccessKey ID and AccessKey Secret.
export AWS_ACCESS_KEY_ID=<Alibaba Cloud AccessKey ID>
export AWS_SECRET_ACCESS_KEY=<Alibaba Cloud AccessKey Secret>
export AWS_REGION=<region, for example cn-hangzhou>
# Optional. Set this when you use STS temporary credentials
export AWS_SESSION_TOKEN=<Alibaba Cloud STS TOKEN>
Important: When you use environment variables, both the driver and the executors must be able to read them. In YARN mode, inject the variables on every cluster node; in Kubernetes mode, inject them into the pod. If you cannot do that, specify the credentials explicitly through the Spark configuration items described below.
Instead of environment variables, you can pass credentials explicitly in PySpark or Spark SQL through the Spark catalog configuration items. This suits multi-catalog setups and cases where setting environment variables is impractical.
# S3FileIO data plane credentials
spark.sql.catalog.oss_tables.s3.access-key-id=<Alibaba Cloud AccessKey ID>
spark.sql.catalog.oss_tables.s3.secret-access-key=<Alibaba Cloud AccessKey Secret>
spark.sql.catalog.oss_tables.client.region=<region, for example cn-hangzhou>
# Optional. Set this when you use STS temporary credentials
spark.sql.catalog.oss_tables.s3.session-token=<Alibaba Cloud STS TOKEN>
# REST Catalog signing credentials
spark.sql.catalog.oss_tables.rest.access-key-id=<Alibaba Cloud AccessKey ID>
spark.sql.catalog.oss_tables.rest.secret-access-key=<Alibaba Cloud AccessKey Secret>
spark.sql.catalog.oss_tables.rest.signing-region=<region, for example cn-hangzhou>
# Optional. Set this when you use STS temporary credentials
spark.sql.catalog.oss_tables.rest.session-token=<Alibaba Cloud STS TOKEN>
OSS Tables exposes an Iceberg REST Catalog endpoint, and Spark manages table metadata through it. The endpoint format is as follows:
https://{region}-internal.oss-tables.aliyuncs.com/iceberg
https://{region}.oss-tables.aliyuncs.com/iceberg
OSS Tables also exposes the access endpoint that S3FileIO uses to reach the OSS data plane, and Spark reads table data through it. The endpoint format is as follows:
https://oss-{region}-internal.aliyuncs.com
https://oss-{region}.aliyuncs.com
Note: Do not set io-impl to org.apache.iceberg.hadoop.HadoopFileIO.
Iceberg is designed to avoid LIST operations, and an OSS Table Bucket — a storage type tuned specifically for Iceberg — blocks them outright. HadoopFileIO builds on file semantics over object storage and issues LIST operations to stay compatible with general-purpose scenarios, so you cannot use it to access data in an OSS Table Bucket.
The following example uses the Table Bucket name my-data-lake in region cn-hangzhou, which gives the Table Bucket ARN acs:osstables:cn-hangzhou:{accountId}:bucket/my-data-lake.
from pyspark.sql import SparkSession
spark = SparkSession.builder \
.appName("OSS Tables Demo") \
.config("spark.jars", "/path/to/iceberg-spark-runtime-3.5_2.12-1.10.1.jar,"
"/path/to/iceberg-aws-bundle-1.10.1.jar") \
.config("spark.sql.extensions", "org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions") \
.config("spark.sql.catalog.oss_tables", "org.apache.iceberg.spark.SparkCatalog") \
.config("spark.sql.catalog.oss_tables.catalog-impl", "org.apache.iceberg.rest.RESTCatalog") \
.config("spark.sql.catalog.oss_tables.uri", "https://cn-hangzhou-internal.oss-tables.aliyuncs.com/iceberg") \
.config("spark.sql.catalog.oss_tables.warehouse", "acs:osstables:cn-hangzhou:{accountId}:bucket/my-data-lake") \
.config("spark.sql.catalog.oss_tables.rest.sigv4-enabled", "true") \
.config("spark.sql.catalog.oss_tables.rest.signing-region", "cn-hangzhou") \
.config("spark.sql.catalog.oss_tables.rest.signing-name", "osstables") \
.config("spark.sql.catalog.oss_tables.io-impl", "org.apache.iceberg.aws.s3.S3FileIO") \
.config("spark.sql.catalog.oss_tables.s3.endpoint", "https://oss-cn-hangzhou-internal.aliyuncs.com") \
.getOrCreate()
spark-sql \
--jars /path/to/iceberg-spark-runtime-3.5_2.12-1.10.1.jar,/path/to/iceberg-aws-bundle-1.10.1.jar \
--conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions \
--conf spark.sql.catalog.oss_tables=org.apache.iceberg.spark.SparkCatalog \
--conf spark.sql.catalog.oss_tables.catalog-impl=org.apache.iceberg.rest.RESTCatalog \
--conf spark.sql.catalog.oss_tables.uri=https://cn-hangzhou-internal.oss-tables.aliyuncs.com/iceberg \
--conf spark.sql.catalog.oss_tables.warehouse=acs:osstables:cn-hangzhou:{accountId}:bucket/my-data-lake \
--conf spark.sql.catalog.oss_tables.rest.sigv4-enabled=true \
--conf spark.sql.catalog.oss_tables.rest.signing-region=cn-hangzhou \
--conf spark.sql.catalog.oss_tables.rest.signing-name=osstables \
--conf spark.sql.catalog.oss_tables.io-impl=org.apache.iceberg.aws.s3.S3FileIO \
--conf spark.sql.catalog.oss_tables.s3.endpoint=https://oss-cn-hangzhou-internal.aliyuncs.com
| Parameter | Required | Description |
|---|---|---|
catalog-impl |
Yes | Always org.apache.iceberg.rest.RESTCatalog, which selects the REST Catalog. |
uri |
Yes | The REST Catalog endpoint URL. Format: • Internal endpoint: https://{region}-internal.oss-tables.aliyuncs.com/iceberg• Public endpoint: https://{region}.oss-tables.aliyuncs.com/iceberg
|
warehouse |
Yes | The Table Bucket ARN. Format: acs:osstables:<Region>:<Alibaba Cloud account ID>:bucket/<Table Bucket name>. |
rest.sigv4-enabled |
Yes | Always true, which enables sigv4 signature authentication. |
rest.signing-region |
No (when credentials are supplied through environment variables) | The REST Catalog signing region, which must match the region of the Table Bucket, for example cn-hangzhou. You can omit it if you set the AWS_REGION environment variable; it is required when you pass credentials through Spark configuration items. |
rest.signing-name |
Yes | The signing service name, always osstables. |
io-impl |
Yes | The FileIO implementation Iceberg uses to read and write the underlying data files, always org.apache.iceberg.aws.s3.S3FileIO. |
s3.endpoint |
Yes | The endpoint S3FileIO uses to reach the OSS data plane. It must include the https:// prefix. Format:• Internal endpoint: https://oss-{region}-internal.aliyuncs.com• Public endpoint: https://oss-{region}.aliyuncs.com
|
Once connected, use standard SQL statements to work with your data.
A namespace groups tables logically and plays the same role as a database.
-- List existing namespaces
SHOW NAMESPACES IN oss_tables;
-- Create a namespace
CREATE NAMESPACE oss_tables.my_namespace;
-- Drop a namespace (drop all tables in it first)
DROP NAMESPACE oss_tables.my_namespace;
-- Create a non-partitioned table
CREATE TABLE oss_tables.my_namespace.users (
id BIGINT NOT NULL COMMENT 'User ID',
name STRING COMMENT 'User name',
email STRING COMMENT 'Email',
created_at TIMESTAMP COMMENT 'Creation time'
) USING iceberg;
-- Create a partitioned table (partitioned by day)
CREATE TABLE oss_tables.my_namespace.events (
id BIGINT NOT NULL,
event_type STRING,
data STRING,
ts TIMESTAMP
) USING iceberg
PARTITIONED BY (days(ts));
-- List all tables in the namespace
SHOW TABLES IN oss_tables.my_namespace;
-- View the table schema
DESCRIBE TABLE oss_tables.my_namespace.users;
-- Drop a table (OSS Tables requires the PURGE keyword; otherwise you get the error: OSS Tables only supports dropping tables with purge enabled)
DROP TABLE oss_tables.my_namespace.users PURGE;
-- Insert data
INSERT INTO oss_tables.my_namespace.users VALUES
(1, 'Zhangsan', 'zhangsan@example.com', TIMESTAMP '2024-01-15 10:30:00'),
(2, 'Lisi', 'lisi@example.com', TIMESTAMP '2024-01-16 14:20:00'),
(3, 'Wangwu', 'wangwu@example.com', TIMESTAMP '2024-01-17 09:15:00');
-- Query the whole table
SELECT * FROM oss_tables.my_namespace.users;
-- Filtered query
SELECT * FROM oss_tables.my_namespace.users WHERE id = 2;
-- Aggregate query
SELECT COUNT(*) AS total FROM oss_tables.my_namespace.users;
-- Grouped aggregation
SELECT name, COUNT(*) AS cnt FROM oss_tables.my_namespace.users GROUP BY name;
-- Update data
UPDATE oss_tables.my_namespace.users SET name = 'Zhaoliu' WHERE id = 3;
-- Delete data
DELETE FROM oss_tables.my_namespace.users WHERE id = 1;
-- Verify with a query
SELECT * FROM oss_tables.my_namespace.users ORDER BY id;
-- Insert partitioned data
INSERT INTO oss_tables.my_namespace.events VALUES
(1, 'click', '{"page": "home"}', TIMESTAMP '2024-01-15 10:30:00'),
(2, 'view', '{"page": "product"}', TIMESTAMP '2024-01-15 11:00:00'),
(3, 'click', '{"page": "detail"}', TIMESTAMP '2024-01-16 09:00:00');
-- Query with partition pruning (scans matching partitions only)
SELECT * FROM oss_tables.my_namespace.events
WHERE ts >= TIMESTAMP '2024-01-15 00:00:00'
AND ts < TIMESTAMP '2024-01-16 00:00:00';
-- Aggregate statistics
SELECT event_type, COUNT(*) AS cnt
FROM oss_tables.my_namespace.events
GROUP BY event_type;
Iceberg supports time travel queries, so you can read a data snapshot as of a point in the past.
-- View snapshot history
SELECT snapshot_id, committed_at, operation
FROM oss_tables.my_namespace.users.snapshots;
-- Query historical data by snapshot ID
SELECT * FROM oss_tables.my_namespace.users
VERSION AS OF <snapshot_id>;
-- Query data as of a specific point in time
SELECT * FROM oss_tables.my_namespace.users
TIMESTAMP AS OF TIMESTAMP '2024-01-16 00:00:00';
-- View the data file layout
SELECT * FROM oss_tables.my_namespace.users.files;
• Version requirements: We recommend Spark 3.5 or later with Iceberg 1.10.1. The Spark version must match the version of the iceberg-spark-runtime JAR file (for example, Spark 3.5 pairs with iceberg-spark-runtime-3.5_2.12).
• Credential configuration: S3FileIO and REST Catalog sigv4 signing use the same AccessKey ID and AccessKey Secret pair. We recommend setting them through the following environment variables, which cover both REST Catalog signing and S3FileIO data access:
AWS_ACCESS_KEY_ID: your Alibaba Cloud AccessKey IDAWS_SECRET_ACCESS_KEY: your Alibaba Cloud AccessKey SecretAWS_REGION: the region of the Table Bucket, used for REST Catalog signing. Once you set this variable, you can omit rest.signing-region from the catalog configuration.• Table format: OSS Tables currently supports only the Iceberg format. You must specify USING iceberg when you create a table.
• Data maintenance: OSS Tables has built-in file compaction, snapshot expiration, and orphan file cleanup, so you do not need to run Iceberg maintenance procedures manually in Spark. For details, see Data maintenance.
• OSS Tables endpoint support:
https://{region}-internal.oss-tables.aliyuncs.com/iceberg
https://{region}.oss-tables.aliyuncs.com/iceberg
Getting started:
• OSS Tables
https://www.alibabacloud.com/help/oss/user-guide/quick-start
• JAR files
• Data maintenance
https://www.alibabacloud.com/help/oss/user-guide/data-maintenance
1,534 posts | 515 followers
FollowJustin See - June 19, 2026
Alibaba Cloud Community - September 16, 2026
Alibaba Cloud MaxCompute - December 22, 2021
Apache Flink Community - July 5, 2024
Alibaba Clouder - April 4, 2019
Apache Flink Community China - July 28, 2020
1,534 posts | 515 followers
Follow
Hybrid Cloud Distributed Storage
Provides scalable, distributed, and high-performance block storage and object storage services in a software-defined manner.
Learn More
OSS(Object Storage Service)
An encrypted and secure cloud storage service which stores, processes and accesses massive amounts of data from anywhere in the world
Learn More
Data Lake Storage Solution
Build a Data Lake with Alibaba Cloud Object Storage Service (OSS) with 99.9999999999% (12 9s) availability, 99.995% SLA, and high scalability
Learn More
Storage Capacity Unit
Plan and optimize your storage budget with flexible storage services
Learn MoreMore Posts by Alibaba Cloud Community