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

问题描述 投票:0回答:1

我正在 Go 中构建一个 Arrow Flight SQL 服务器,包装 DuckDB 来查询大量 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 上对此进行了测试。

go parquet duckdb apache-arrow-flight
1个回答
0
投票

首先按照与 sqlite 相同的方式创建数据库:

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

之后您可以这样加载镶木地板文件:

_, _ = 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")

希望有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.