Apache Iceberg Go

repository·main·Indexed 19 days ago

https://github.com/apache/iceberg-go

A Golang implementation of the Apache Iceberg table specification. It provides programmatic interfaces and a CLI to interact with Iceberg tables, supporting multiple catalogs (REST, Hive, Glue, SQL, Hadoop) and filesystems (S3, GCS, Azure Blob Storage, Local). Key capabilities include metadata operations, write operations (append, rewrite, overwrite), and management of namespaces, tables, branches, and tags.

Tokens
53.2K
Snippets
163
Records
242
Agent score
64%

What's inside iceberg-go

  1. Introduction to Apache Iceberg Go

    main
    Apache Iceberg Go is a Go-native implementation of the Apache Iceberg open table format. It allows developers to read and write Iceberg tables directly from Go services and tooling without requiring a JVM. This makes it suitable for lightweight microservices, CLI tools, and other Go-based data engineering pipelines.
  2. Choosing an Iceberg implementation

    main

    Apache Iceberg has multiple official implementations across different languages. While the table format and catalog protocols are identical across all implementations, you should choose the one that matches your runtime environment. All implementations target the same core Iceberg specification.

    | Project | Language | Repository | Documentation |
    |---|---|---|---|
    | Apache Iceberg | Java (reference) | [apache/iceberg](https://github.com/apache/iceberg) | [iceberg.apache.org](https://iceberg.apache.org/) |
    | PyIceberg | Python | [apache/iceberg-python](https://github.com/apache/iceberg-python) | [py.iceberg.apache.org](https://py.iceberg.apache.org/) |
    | iceberg-rust | Rust | [apache/iceberg-rust](https://github.com/apache/iceberg-rust) | [rust.iceberg.apache.org](https://rust.iceberg.apache.org/) |
    | iceberg-cpp | C++ | [apache/iceberg-cpp](https://github.com/apache/iceberg-cpp) | [cpp.iceberg.apache.org](https://cpp.iceberg.apache.org/) (early stage) |
  3. Understand Partitioning and Partition Transforms

    main

    Partitioning logically divides table data to improve query performance via selective reading.

    Partitioning Terms

    • Partition: A logical division based on column values.
    • Partition Spec: Defines how data is partitioned using source columns and transformations.
    • Partition Field: A field in the spec defining how a source column is transformed.
    • Partition Path: The file system path structure (e.g., partition_name=value/).

    Partition Transforms

    TransformDescription
    identityUse the column value directly
    bucket[n]Hash the value into n buckets
    truncate[n]Truncate strings to n characters
    yearExtract year from date/timestamp
    monthExtract month from date/timestamp
    dayExtract day from date/timestamp
    hourExtract hour from timestamp
    voidAlways returns null (for unpartitioned tables)
  4. Comparison of Iceberg implementations by use case

    main

    Select an implementation based on your primary language and ecosystem:

    • Java (Reference): The canonical choice for JVM workloads and query engines like Spark, Flink, Trino, Hive, Presto, and Dremio.
    • PyIceberg (Python): Best for data science and ML workflows involving the Python dataframe ecosystem (PyArrow, Pandas, Polars, DuckDB, Daft, Ray).
    • iceberg-rust (Rust): Used by pyiceberg-core, DataFusion-based engines, and other Rust-native systems.
    • iceberg-cpp (C++): An early-stage implementation for native C++ integration.
    • iceberg-go (Go): Ideal for Go services and streaming Apache Arrow record batches.
  5. Define column references with Terms

    main

    A term represents the left-hand side of a predicate.

    • Unbound Terms: Use iceberg.Reference("column_name") to name a column. This is the standard way to build expressions; typing is resolved later during the binding phase against a schema.
    • Bound Terms: These are resolved forms produced by calling Reference.Bind(schema, caseSensitive). You typically only interact with these when writing custom expression visitors.
    // Create an unbound term (most common use case)
    term := iceberg.Reference("column_name")
  6. Understand Schema Evolution and Time Travel

    main

    Schema Evolution

    Iceberg allows modifying a table's schema over time while maintaining backward compatibility:

    • Column Addition: Adding new (typically optional) columns.
    • Column Deletion: Removing columns (logically or physically).
    • Column Renaming: Changing names while preserving data/type info.
    • Type Evolution: Changing types in compatible ways (e.g., int32 to int64).

    Time Travel

    • Time Travel: Querying a table as it existed at a specific point in time using snapshot timestamps.
    • Snapshot Isolation: Ensuring queries see a consistent view of data from a specific snapshot.
  7. Understand Iceberg Core Concepts

    main

    The Iceberg ecosystem relies on several key abstractions to manage data and metadata:

    • Catalog: A centralized service (e.g., Hive metastore, AWS Glue, REST API, or SQL) that manages table metadata and provides a unified interface for accessing tables.
    • Table: A collection of data files organized by a Schema, supporting ACID transactions and schema evolution.
    • Snapshot: A point-in-time view of a table's data representing the state after an operation (append, overwrite, etc.).
    • Manifest: A metadata file listing data files and their metadata (location, partition info, etc.).
    • Manifest List: A file containing references to manifest files for a specific snapshot, used for efficient data discovery.
  8. Use constants for dynamic filter composition

    main

    When building filters dynamically (e.g., in a loop or conditional logic), use iceberg.AlwaysTrue{} and iceberg.AlwaysFalse{} as identity elements.

    • Use AlwaysTrue{} as the starting point when folding multiple clauses with NewAnd.
    • Use AlwaysFalse{} as the starting point when folding multiple clauses with NewOr.
    iceberg.AlwaysTrue{}
    iceberg.AlwaysFalse{}
  9. Iceberg Go Spec Format Version Coverage

    main

    Apache Iceberg Go supports table format versions 1, 2, and 3. The maximum supported version is enforced in table/metadata.go (supportedTableFormatVersion = 3).

    V1

    All V1 features are supported. V1 serves as the baseline format version.

    V2

    Supported features include:

    • Sequence numbers
    • Manifest entry status (added / existing / deleted)
    • Positional deletes (read + write)
    • Equality deletes (read + write). Write via Transaction.WriteEqualityDeletes; row-level commits via Transaction.NewRowDelta.
    • Partition spec evolution
    • Sort order enforcement on write

    Note: ReplaceDataFiles using OpReplace is currently pending.

    V3

    Supported features include:

    • Nanosecond timestamps (timestamp_ns, timestamptz_ns)
    • Default values (initial-default, write-default)
    • Row lineage (_row_id, _last_updated_sequence_number)
    • Encryption keys in metadata
    • Variant type, non-shredded
    • Deletion vectors (read, and unpartitioned write)
    • Geometry / Geography types (schema)

    Note: Variant type shredded reader/writer, partitioned deletion vector writes, and Geometry/Geography transforms/statistics/pruning are currently in progress.

  10. Configure Concurrency settings

    main

    Concurrency can be controlled globally via the CLI config, or overridden per-operation in code:

    • Global: Set max-workers in ~/.iceberg-go.yaml (Default: 5).
    • Per-Scan: Use table.WithMaxConcurrency(n int).
    • Per-Write: Use WithMaxWriteWorkers(n int) on WriteRecords methods.
    • Single-threaded: Use WithClusteredWrite() to force single-threaded writes (mutually exclusive with WithMaxWriteWorkers).
  11. Understand Iceberg Table Operations

    main

    Common operations used to modify table state and create new snapshots:

    • Append: Adds new data files without removing existing ones.
    • Overwrite: Replaces existing data files with new ones, typically based on a partition predicate.
    • Delete: Removes data files by marking them as deleted or removing references.
    • Replace: Replaces all data in a table, typically for full refreshes.
  12. How LocationProviders work

    main

    The LocationProvider determines how file paths are generated for tables. Currently, there are two implementations:

    1. simpleLocationProvider: The default implementation.
    2. objectStoreLocationProvider: Used for hashed object-storage layouts. This is automatically selected when the table property write.object-storage.enabled is set to true.

    Note: The LocationProvider is not currently user-pluggable; it is selected based on table properties.