First Steps
Create your first namespace and table in Bingsan
First Steps
After installing Bingsan, follow this guide to create your first namespace and table.
Understanding the Hierarchy
Iceberg catalogs use a hierarchical structure:
Catalog (Bingsan)
└── Namespace (e.g., "analytics", "raw.events")
└── Table (e.g., "user_events")
└── Metadata (schema, partitions, snapshots)Create a Namespace
Namespaces are containers for tables. They can be nested using dots or arrays.
# Create a simple namespace
curl -X POST http://localhost:8181/v1/namespaces \
-H "Content-Type: application/json" \
-d '{
"namespace": ["analytics"],
"properties": {
"owner": "data-team",
"description": "Analytics data warehouse"
}
}'Response:
{
"namespace": ["analytics"],
"properties": {
"owner": "data-team",
"description": "Analytics data warehouse"
}
}Nested Namespaces
Create a nested namespace:
curl -X POST http://localhost:8181/v1/namespaces \
-H "Content-Type: application/json" \
-d '{
"namespace": ["analytics", "events"],
"properties": {}
}'Referencing Nested Namespaces in URLs
When referencing nested namespaces in REST API URLs (GET, DELETE, HEAD), use one of these formats:
Option 1: Dot-separated (simple)
# Get nested namespace
curl http://localhost:8181/v1/namespaces/analytics.events
# Delete nested namespace
curl -X DELETE http://localhost:8181/v1/namespaces/analytics.eventsOption 2: URL-encoded unit separator (%1F)
# For namespaces with dots in their names, use %1F separator
curl http://localhost:8181/v1/namespaces/analytics%1FeventsNote: Use
%1F(unit separator) when namespace parts contain dots, e.g.,["my.app", "events"]should be encoded asmy.app%1Fevents.
List Namespaces
# List all namespaces
curl http://localhost:8181/v1/namespacesResponse:
{
"namespaces": [
["analytics"],
["analytics", "events"]
]
}Filter by Parent
# List child namespaces
curl "http://localhost:8181/v1/namespaces?parent=analytics"Get Namespace Details
curl http://localhost:8181/v1/namespaces/analyticsResponse:
{
"namespace": ["analytics"],
"properties": {
"owner": "data-team",
"description": "Analytics data warehouse"
}
}Create a Table
Tables require a schema definition following the Iceberg specification.
curl -X POST http://localhost:8181/v1/namespaces/analytics/tables \
-H "Content-Type: application/json" \
-d '{
"name": "user_events",
"schema": {
"type": "struct",
"schema-id": 0,
"fields": [
{"id": 1, "name": "event_id", "required": true, "type": "string"},
{"id": 2, "name": "user_id", "required": true, "type": "long"},
{"id": 3, "name": "event_type", "required": true, "type": "string"},
{"id": 4, "name": "event_time", "required": true, "type": "timestamptz"},
{"id": 5, "name": "properties", "required": false, "type": {"type": "map", "key-id": 6, "key": "string", "value-id": 7, "value": "string"}}
]
},
"partition-spec": {
"spec-id": 0,
"fields": [
{"source-id": 4, "field-id": 1000, "name": "event_day", "transform": "day"}
]
},
"properties": {
"format-version": "2",
"write.parquet.compression-codec": "zstd"
}
}'List Tables
curl http://localhost:8181/v1/namespaces/analytics/tablesResponse:
{
"identifiers": [
{"namespace": ["analytics"], "name": "user_events"}
]
}Load Table Metadata
curl http://localhost:8181/v1/namespaces/analytics/tables/user_eventsThis returns the full table metadata including:
- Current schema
- Partition specification
- Sort order
- Current snapshot
- Table properties
Check Table Exists
Use HEAD request for lightweight existence check:
curl -I http://localhost:8181/v1/namespaces/analytics/tables/user_eventsReturns HTTP 200 if exists, 404 if not.
Update Namespace Properties
curl -X POST http://localhost:8181/v1/namespaces/analytics/properties \
-H "Content-Type: application/json" \
-d '{
"updates": {
"owner": "platform-team"
},
"removals": ["description"]
}'Delete Resources
Drop Table
curl -X DELETE http://localhost:8181/v1/namespaces/analytics/tables/user_eventsDelete Namespace
Namespaces must be empty before deletion.
curl -X DELETE http://localhost:8181/v1/namespaces/analyticsUsing with Spark
Once your catalog is set up, connect from Spark:
from pyspark.sql import SparkSession
spark = SparkSession.builder \
.appName("Bingsan Example") \
.config("spark.sql.catalog.bingsan", "org.apache.iceberg.spark.SparkCatalog") \
.config("spark.sql.catalog.bingsan.type", "rest") \
.config("spark.sql.catalog.bingsan.uri", "http://localhost:8181") \
.getOrCreate()
# List tables
spark.sql("SHOW TABLES IN bingsan.analytics").show()
# Query table
spark.sql("SELECT * FROM bingsan.analytics.user_events LIMIT 10").show()