Go Iterator 从 Bigquery 读取 100 万行,比 Java 或 kotlin 慢 10 倍?
Posted
技术标签:
【中文标题】Go Iterator 从 Bigquery 读取 100 万行,比 Java 或 kotlin 慢 10 倍?【英文标题】:Go Iterator reading 1 million rows from Bigquery 10x slower than Java or kotlin? 【发布时间】:2021-05-09 18:08:34 【问题描述】:我的目的是使用 Go 查询 Biquery 并索引 Elasticsearch 中的一些字段。这将是一个一次性的批处理作业。由于团队拥有 Java 知识,我们决定对这两种语言进行基准测试。我注意到 Go 使用“迭代器方式”工作缓慢。
为什么会有这种时间差异?
我是否遗漏了 Go 中的某些客户端或查询配置,或者这是预期的行为?
如何提高阅读时间?
Java/kotlin 和 Go:
在完全相同的环境中运行。 Bigquery 数据集 200GB 相同的“sql”查询,连接两个表,只检索 12 个 ish 字段。限制 100 万行。 使用交互式查询从 GCP 文档中为两种语言运行示例代码:https://cloud.google.com/bigquery/docs/running-queries。(我已经简化了代码)
转到 1.16.3
...
type Test struct
TestNo *big.Rat `bigquery:"testNo,nullable"`
TestId bigquery.NullString `bigquery:"testId"`
TestTime bigquery.NullDateTime `bigquery:"testTime"`
FirstName bigquery.NullString `bigquery:"firstName"`
LastName bigquery.NullString `bigquery:"lastName"`
Items []ItemTest `bigquery:"f0_"`
type ItemTest struct
ItemType bigquery.NullString `bigquery:"itemType"`
ItemNo bigquery.NullString `bigquery:"itemNo"`
ProductNo *big.Rat `bigquery:"productNo,nullable"`
Qty *big.Rat `bigquery:"qty,nullable"`
Name bigquery.NullString `bigquery:"name"`
Price *big.Rat `bigquery:"price,nullable"`
ctx := context.Background()
client, err := bigquery.NewClient(ctx, projectID)
if err != nil
// TODO: Handle error.
q := client.Query(myQuery)
it, err := q.Read(ctx)
if err != nil
// TODO: Handle error.
for
start := time.Now().UTC()
var t Test
err := it.Next(&t)
if err == iterator.Done
break
if err != nil
// TODO: Handle error.
end += time.Since(start)
IndexToES(t)
fmt.Println(end) //13 minutes.
...
读取和映射到 Go 结构需要 13 分钟。
科特林
...
val start: BigDecimal = Instant.now().toEpochMilli().toBigDecimal().setScale(3)
val bigquery = BigQueryOptions.newBuilder()
.setCredentials(credentials)
.setProjectId(PROJECT_ID)
.build()
.service
val queryConfig = QueryJobConfiguration.newBuilder(query).build()
val tableResult = bigquery.query(queryConfig)
val test = results.iterateAll()
.map myMapper.mapToTest(it)
val end: BigDecimal = Instant.now().toEpochMilli().toBigDecimal().setScale(3)
logResults(start, end) // 60000ms = 1minute
fun logResults(start: BigDecimal, end: BigDecimal)
println("query: " + (pitB - pitA).setScale(0) + "ms")
//iterate through test and indexing at the same time
...
需要 1 分钟...
【问题讨论】:
请阅读:Can I ask only one question per post? 我不知道答案,因为我对go
知之甚少(更不用说它的内部结构),但它一定又是JVM
的奇妙表现方式
【参考方案1】:
sn-p 都不完整,所以不清楚这是否是苹果对苹果。如果您想知道 Go 程序的时间在哪里,请考虑利用 pprof。
要指出的另一件事是,如果您正在读取数百万行查询输出,您将需要查看BigQuery Storage API。使用它而不是您当前正在测试的迭代器可以使这两种语言的速度更快。
【讨论】:
以上是关于Go Iterator 从 Bigquery 读取 100 万行,比 Java 或 kotlin 慢 10 倍?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Dataflow 中的 PCollection 读取 bigQuery