Skip to content
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 160 additions & 0 deletions docs/gcs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
---
title: "GCS"
url: gcs
menu:
main:
parent: Integrations
identifier: gcs_integration
weight: 0
---
<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-->

# Iceberg GSC Integration

@bryanck bryanck Aug 7, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: I think you meant GCS


Google Cloud Storage (GCS) is a scalable object storage service known for its durability, throughput, and availability. It is designed to handle large amounts of unstructured data, making it an excellent choice for significant data operations. When GCS's storage capabilities are combined with Apache Iceberg's handling of large tabular datasets, a powerful tool for extensive data management is created. This combination allows for storing vast amounts of data and the execution of complex data operations directly on the data stored in GCS.

## Setting Up Google Cloud Storage (GCS)

### Setting Up a Bucket in GCS

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is needed in Iceberg docs. This would be more appropriate for a "Using Iceberg with GCS" tutorial, but not the doc on GCS FileIO.


Here's how to create a bucket in GCS:

- **Initialize the Google Cloud CLI**: Run the gcloud init command to start the initialization process of Google Cloud CLI, which sets up the Google Cloud environment on your local machine.

- **Create a Cloud Storage bucket**: Navigate to the Cloud Storage Buckets page in the Google Cloud Console. Click "Create bucket", enter your details, and click "Create".

## Configuring Apache Iceberg to Use GCS

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this maybe show how this can be used via the Java API vs Spark? Most users would likely want to know how to use GCS with Spark

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. We don't expect anyone to instantiate these directly. They are provided by Table instances.


Apache Iceberg uses the GCSFileIO to read and write data from/to GCS. To configure this:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Apache Iceberg uses the GCSFileIO to read and write data from/to GCS. To configure this:
Apache Iceberg uses the `GCSFileIO` to read and write data from/to GCS. To configure this:


- **Initialize `GCSFileIO`**: Create an instance of `GCSFileIO` by calling its constructor and supplying a `com.google.cloud.storage.Storage` instance and `GCPProperties` instance. This Storage instance will be used as the storage service engine, and GCPProperties hold GCP-specific configurations.

```java
GCSFileIO gcsFileIO = new GCSFileIO(storageSupplier, gcpProperties);
```

- **Configure GCSFileIO**: Once you have the `GCSFileIO` object, you can configure it to use your GCS bucket. You do this by calling the initialize method of `GCSFileIO` and passing a map of properties. This map holds the GCS bucket name and other required GCS settings.

```java
Map<String, String> properties = new HashMap<>();
properties.put("inputDataLocation", "gs://my_bucket/data/");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where is inputDataLocation actually being used?

properties.put("metadataLocation", "gs://my_bucket/metadata/");
gcsFileIO.initialize(properties);
```

Within these property key-value pairs, inputDataLocation and metadataLocation are the locations in your GCS bucket where your data and metadata are stored. Update `"gs://my_bucket/data/" ` and `"gs://my_bucket/metadata/" ` to reflect the corresponding paths of your GCS bucket.

### Example Use of GCSFileIO

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is more useful for a general FileIO doc, not one specific to GCS.


Once `GCSFileIO` is initialized and configured, you can interact with the data housed on GCS. Below, we will demonstrate how to create and access an `InputFile` and an `OutputFile`.

- **Creating an InputFile**: To create an `InputFile` for reading data from your GCS bucket, you can use the `newInputFile` method.

```java
InputFile inputFile = gcsFileIO.newInputFile("gs://my_bucket/data/my_data.parquet");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: unnecessary newline.

@mhmohona mhmohona Aug 6, 2023

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its needed for formatting purpose otherwise it violates this rule - https://github.com/DavidAnson/markdownlint/blob/v0.29.0/doc/md031.md

```

Replace `"gs://my_bucket/data/my_data.parquet"` with the path of the data you want to read.

- **Creating an OutputFile**: To write data to your GCS bucket, you would establish an OutputFile using the newOutputFile method.

```java
OutputFile outputFile = gcsFileIO.newOutputFile("gs://my_bucket/data/my_output.parquet");
```

Again, replace `"gs://my_bucket/data/my_output.parquet"` with the path where you'd like to write your data.

These steps will allow you to set up GCS as your storage layer for Apache Iceberg and interact with the data stored in GCS using the `GCSFileIO` class.

## Loading Data into Iceberg Tables

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the main thing here is to set up a warehouse with a gs:// URI for its base warehouse location.


### Add Iceberg to Spark environment

To load data into Iceberg tables using Apache Spark, you must first add Iceberg to your Spark environment. It can be done using the `--packages` option when starting the Spark shell or Spark SQL:

```bash
spark-shell --packages org.apache.iceberg:iceberg-spark-runtime-3.2_2.12:1.3.1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
spark-shell --packages org.apache.iceberg:iceberg-spark-runtime-3.2_2.12:1.3.1
spark-shell --packages org.apache.iceberg:iceberg-spark-runtime-3.4_2.12:1.3.1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we want a tutorial for starting Spark here. It is good to know what additional libraries are needed for running GCSFileIO if you are using the runtime bundle though.

spark-sql --packages org.apache.iceberg:iceberg-spark-runtime-3.2_2.12:1.3.1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
spark-sql --packages org.apache.iceberg:iceberg-spark-runtime-3.2_2.12:1.3.1
spark-sql --packages org.apache.iceberg:iceberg-spark-runtime-3.4_2.12:1.3.1

```

### Configure Spark Catalogs

Catalogs in Iceberg are used to track tables. They can be configured using properties under `spark.sql.catalog.(catalog_name)`. Here is an example of how to configure a catalog:

```bash
spark-sql --packages org.apache.iceberg:iceberg-spark-runtime-3.2_2.12:1.3.1\

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
spark-sql --packages org.apache.iceberg:iceberg-spark-runtime-3.2_2.12:1.3.1\
spark-sql --packages org.apache.iceberg:iceberg-spark-runtime-3.4_2.12:1.3.1\

--conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions \
--conf spark.sql.catalog.spark_catalog=org.apache.iceberg.spark.SparkSessionCatalog \
--conf spark.sql.catalog.spark_catalog.type=hive \
--conf spark.sql.catalog.local=org.apache.iceberg.spark.SparkCatalog \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be easier to understand when showing an example where only a single catalog is being initialized (so either local or spark_catalog)

--conf spark.sql.catalog.local.type=hadoop \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Examples should not use the hadoop catalog type. hive is probably better.

--conf spark.sql.catalog.local.warehouse=$PWD/warehouse \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would point to the respective gs:... bucket?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, agreed.

--conf spark.sql.defaultCatalog=local

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this have a --conf spark.sql.catalog.local.io-impl=org.apache.iceberg.gcp.gcs.GCSFileIO to properly pick up GCSFileIO?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ResolvingFileIO should pick it based on the gs scheme.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 ResolvingFileIO will automatically select GCSFileIO based on the scheme in the next release. It might be better to use the REST catalog as an example as it is easier to set up than a HMS, and no io-impl needs to be set.

```

This configuration creates a path-based catalog named local for tables under `$PWD/warehouse` and adds support for Iceberg tables to Spark's built-in catalog.

### Load data into Iceberg Tables

- **CSV format**:

```java
val csvDF = spark.read.format("csv").option("header", "true").load("path_to_your_csv")
csvDF.write.format("iceberg").mode("append").save("local.db.your_table")
```

- **Parquet format**:

```java
val parquetDF = spark.read.format("parquet").load("path_to_your_parquet")
parquetDF.write.format("iceberg").mode("append").save("local.db.your_table")
```

Specify `path_to_your_csv` and `path_to_your_parquet` with the actual paths of your CSV and Parquet files, respectively. Replace `your_table` with the name of the table you want to create in Iceberg.

> Please note that Iceberg table names are case-sensitive; hence ensure the terms you use in the above code are case-correct.

## Querying Data from Iceberg Tables

### Using DataFrameReader API

You can use Spark's `read.format("iceberg")` method to read an Iceberg table into a DataFrame. Here is an example:

```java
// Read an Iceberg table into a DataFrame
var df = spark.read.format("iceberg").load("local.db.one");

// Perform operations on the DataFrame
df.show();
df.filter(df.col("column_name").gt(100)).show();
```

In the above example, you can replace `"local.db.one"` with the name of your Iceberg table. The `show()` method is used to display the contents of the DataFrame. The `filter()` method is used to filter the DataFrame based on a condition.

### Using Spark SQL

You can also use Spark SQL to query data from Iceberg tables. Here is an example:

```bash
// Query data from an Iceberg table using Spark SQL
spark.sql("SELECT * FROM local.db.one").show();
spark.sql("SELECT column_name, count(*) FROM local.db.one GROUP BY column_name").show();
```

In the above example, you can replace `"local.db.one"` with the name of your Iceberg table. The `sql()` method performs SQL queries on the Iceberg table.