Go语言的Bigquery客户端比GUI慢很多(秒级别与毫秒级别)。

5
    q := i.client.Query(query)

    job, err := q.Run(ctx)
    if err != nil {
        <handle>
    }
    status, err := job.Wait(ctx)
    if err != nil {
        <handle>
    }
    if err = status.Err(); err != nil {
        <handle>
    }

    it, err := job.Read(ctx)
    if err != nil {
        <handle>
    }

以下是我用来查询BigQuery表的代码。其中client字段是*bigquery.Client类型。

查询本身非常简单,如下所示:

SELECT field, another_field from some_table LIMIT K OFFSET N

我知道这种类型的分页不是BQ的最佳实践,但这是另外一个讨论的主题。

与在GUI中查询相比,此Run调用需要2-4秒钟而不是几百毫秒。

可能出了什么问题?官方包文档使用与此相同或更多的方法来与BigQuery交互(有时会跳过Wait部分)。

编辑:

事实证明,仅使用Query.Read()速度要快得多:等待作业的时间从3-4秒减少到1秒。

话虽如此,它仍然比GUI慢得多 :)


1
看起来这个问题需要进一步调查,如果您有支持计划,请创建一个新的 GCP 支持案例。否则,您可以在问题跟踪器上打开一个新问题,描述您的问题。 - Prajna Rai T
@PrajnaRaiT,我已经提交了一个工单,但我的初步想法是可能是我做错了什么,而不是BigQuery或Go客户端的问题 :) - Don Draper
作为初始故障排除,通过手动计算时间差或使用go-profiling来确定哪部分代码实际上花费了最多的时间将会很有帮助。 - Suyash Medhavi
1个回答

0

在您提供的示例中,Query.Read()job.Read()之间不应该有任何区别,因为它们使用相同的机制(请查看源代码https://github.com/googleapis/google-cloud-go/blob/bigquery/v1.43.0/bigquery/query.go#L370)。Query.Read()调用job.Run(),然后调用job.Read()

我认为Go客户端与GUI之间的主要区别在于数据读取方式:在Go客户端中,使用rest API分页获取结果(需要找到最大页面大小,但由于http的性质,它相当小)。而GUI似乎使用存储API(docsapi docs),速度快得多。如果您正在获取大量数据,则差异将是显着的。

通过Go客户端进行测试的吉比特连接吞吐量约为2MB/s,使用存储API则为约30MB/s。

很抱歉没有提供完整的参考链接(因为收集它们需要太多时间),但我希望我已经指出了关于BigQuery吞吐量性能的阅读方向。

另一个可能降低BigQuery性能的时刻是优先级(https://pkg.go.dev/cloud.google.com/go/bigquery#QueryConfig)。但默认情况下它是交互式的,如果您没有将其设置为BatchPriority,那么它不是原因。

    // Priority specifies the priority with which to schedule the query.
    // The default priority is InteractivePriority.
    // For more information, see https://cloud.google.com/bigquery/querying-data#batchqueries
    Priority QueryPriority

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接