如何在 Go 中使用 DuckDB 读取 parquet 文件?

How to read parquet files using DuckDB in Go?

提问人:knightcool 提问时间:9/12/2023 更新时间:9/24/2023 访问量:298

问:

我正在用 Go 包装 DuckDB 构建一个 Arrow Flight SQL 服务器来查询大量 parquet 文件(每个文件都有不同的架构)。我希望这些 parquet 文件按需加载到 DuckDB 中(即当它进行查询时),而不是在启动时将所有这些文件加载到 DuckDB 数据库中。

DuckDB CLI 支持这种行为,允许对一组与 glob 模式匹配的文件进行 SQL 查询,这是完美的。但是,当我启动一个简单的 Go Arrow Flight SQL 服务器以连接到 DuckDB 并传递单个 parquet 文件以用作数据源时,我在服务器启动时出现错误。

这是我的测试代码的片段:

func CreateDB() (*sql.DB, error) {
    // Connect to the DuckDB database.
    db, err := sql.Open("duckdb", "parquet:/path/to/local/parquet/file.parquet")
    if err != nil {
        log.Fatal(err)
        return nil, err
    }
    defer db.Close()
    fmt.Println("Connection to DuckDB created successfully!")
    return db, nil
}

func main() {
    host := flag.String("host", "localhost", "IP/Hostname to bind the server to")
    port := flag.String("port", "31337", "Port to bind the server to")

    db, err := CreateDB()
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    srv := NewDuckDBFlightSQLServer(db)
    server := flight.NewServerWithMiddleware(nil)
    server.RegisterFlightService(flightsql.NewFlightServer(srv))
    server.Init(net.JoinHostPort(*host, *port))
    server.SetShutdownOnSignals(os.Interrupt, os.Kill)

    fmt.Println("DuckDB Flight SQL Server started on ", server.Addr(), "...")

    if err := server.Serve(); err != nil {
        log.Fatal(err)
    }
}

运行此代码时出现的错误是:

could not open database: Binder Error: Unrecognized storage type "parquet"
2023/09/12 10:27:13 could not open database: Binder Error: Unrecognized storage type "parquet"

基本上它不喜欢通话中的前缀。删除该前缀会产生不同的(且更明显的)错误parquet:sql.Open()

could not open database: IO Error: The file "/path/to/local/parquet/file.parquet" exists, but it is not a valid DuckDB database file!

使用内存数据库连接到 DuckDB(将第二个参数作为空字符串传递)工作正常,服务器启动成功。sql.Open()

在 Go 中实现这一目标的正确方法是什么?我还没有在 Go 中找到“DuckDB + parquet + arrowFlightSQL”的参考实现(或入门文档)。Go 中的 duckDB 驱动不支持直接查询 parquet 文件吗?

我已经在 Go 1.18.10 上对此进行了测试。

实木复合地板 duckdb apache-arrow-flight

评论

0赞 knightcool 9/13/2023
顺便说一句,这个问题与 Arrow Flight SQL 完全无关。即使启动一个简单的 HTTP Go 服务器来连接到读取 parquet 文件,也会出现同样的错误。

答:

0赞 Ome Eja 9/24/2023 #1

首先创建一个数据库,就像你对 sqlite 所做的那样:

db, err := sql.Open("duckdb", "mydb.db")
if err != nil {
    log.Fatal(err)
    return nil, err
}

之后,您可以以这种方式加载 parquet 文件:

_, _ = db.execute("install 'parquet'")
_, _ = db.execute("load 'parquet'")
_, _ = db.execute("create view mydata as select * from read_parquet('path/to/your/parquet/file'")

最后,您可以通过以下方式查询数据:

_, _ = db.execute("select * from mydata")

在此处查看文档

希望它有所帮助。