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

ddhy6vgd  于 2023-09-28  发布在  Go
关注(0)|答案(1)|浏览(123)

我正在用Go语言构建一个Arrow Flight SQL server, Package 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"

基本上它不喜欢sql.Open()调用中的parquet:前缀。删除该前缀会产生一个不同的(也是更明显的)错误

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上测试过了。

flvlnr44

flvlnr441#

首先创建一个数据库,方法与创建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")

See the doc here
希望有帮助。

相关问题