Using Parquet with Go: A Beginner's Guide

📚 3 min read Tweet this post

Parquet is a columnar storage format that is designed to efficiently store and process large amounts of structured and semi-structured data. It achieves this by organizing data into a set of logical columns, with each column consisting of a sequence of values of the same data type.

The Parquet data format is comprised of three main components:

  1. Metadata: This includes information about the schema of the data, such as the names and types of columns, as well as other metadata such as compression settings and encoding schemes.
  2. Data Pages: These are the actual data values that are stored in the file. Data pages are organized into row groups, which are collections of consecutive rows for a given set of columns.
  3. Index Pages: These are used to speed up the process of locating specific rows in the data file. The index pages contain information about the minimum and maximum values of each column in each row group, as well as the offset of the first data page for each row group.

Parquet is designed to be highly efficient and scalable, with features such as column compression and encoding schemes that are optimized for different data types. This makes it an ideal format for storing and processing large amounts of data in big data environments.

In this article, we will explore how to use Parquet with Go.

To use Parquet in Go, you will need to install the github.com/xitongsys/parquet-go package. This package provides a set of APIs that allow you to read and write Parquet files in Go.

To get started, you can create a new Parquet file using the Create function provided by the package. This function takes a file name and a Parquet schema definition as input and returns a Parquet writer that you can use to write data to the file.

package main

import (
    "github.com/xitongsys/parquet-go/parquet"
    "github.com/xitongsys/parquet-go/writer"
)

func main() {
    f, err := os.Create("example.parquet")
    if err != nil {
        log.Fatalf("Failed to create file: %v", err)
    }

    schema, err := parquet.NewSchema(
        parquet.Field{Name: "id", Type: parquet.Type_INT32, RepetitionType: parquet.RepetitionType_REQUIRED},
        parquet.Field{Name: "name", Type: parquet.Type_BYTE_ARRAY, RepetitionType: parquet.RepetitionType_REQUIRED},
    )
    if err != nil {
        log.Fatalf("Failed to create schema: %v", err)
    }

    pw, err := writer.NewParquetWriter(f, schema, 4)
    if err != nil {
        log.Fatalf("Failed to create writer: %v", err)
    }

    defer pw.WriteStop()

    pw.WriteRow(0, "John")
    pw.WriteRow(1, "Jane")
}

In this example, we create a Parquet file called example.parquet with a schema that defines two fields: id and name. The id field is of type INT32, and the name field is of type BYTE_ARRAY. We then create a Parquet writer with a row group size of 4 and write two rows of data to the file.

To read data from a Parquet file in Go, you can use the OpenFile function provided by the github.com/xitongsys/parquet-go/reader package. This function takes a file name as input and returns a Parquet reader that you can use to read data from the file.

package main

import (
    "github.com/xitongsys/parquet-go/reader"
)

func main() {
    f, err := os.Open("example.parquet")
    if err != nil {
        log.Fatalf("Failed to open file: %v", err)
    }

    pr, err := reader.NewParquetReader(f, nil, 4)
    if err != nil {
        log.Fatalf("Failed to create reader: %v", err)
    }

    defer pr.ReadStop()

    for i := 0; i < int(pr.GetNumRows()); i++ {
        id, _ := pr.ReadInt32("id", i)
        name, _ := pr.ReadString("name", i)
        fmt.Printf("id: %v, name: %v\n", id, name)
    }
}

In this example, we open the example.parquet file and create a Parquet reader with a row group size of 4. We then loop through all therows in the file using the GetNumRows function provided by the reader and read the id and name fields of each row using the ReadInt32 and ReadString functions, respectively.

Parquet supports a variety of compression algorithms, including Gzip, Snappy, and LZ4. In Go, you can enable compression by setting the CompressionType field of the Parquet writer to the desired compression algorithm.

package main

import (
    "github.com/xitongsys/parquet-go/parquet"
    "github.com/xitongsys/parquet-go/writer"
)

func main() {
    f, err := os.Create("example.parquet")
    if err != nil {
        log.Fatalf("Failed to create file: %v", err)
    }

    schema, err := parquet.NewSchema(
        parquet.Field{Name: "id", Type: parquet.Type_INT32, RepetitionType: parquet.RepetitionType_REQUIRED},
        parquet.Field{Name: "name", Type: parquet.Type_BYTE_ARRAY, RepetitionType: parquet.RepetitionType_REQUIRED},
    )
    if err != nil {
        log.Fatalf("Failed to create schema: %v", err)
    }

    pw, err := writer.NewParquetWriter(f, schema, 4)
    if err != nil {
        log.Fatalf("Failed to create writer: %v", err)
    }

    pw.CompressionType = parquet.CompressionCodec_SNAPPY

    defer pw.WriteStop()

    pw.WriteRow(0, "John")
    pw.WriteRow(1, "Jane")
}

In this example, we set the CompressionType field of the Parquet writer to parquet.CompressionCodec_SNAPPY, which enables Snappy compression.

Parquet is a popular columnar storage format that is widely used in big data processing. In Go, you can use the github.com/xitongsys/parquet-go package to read and write Parquet files. You can also enable compression by setting the CompressionType field of the Parquet writer to the desired compression algorithm.

go practical