使用 bigquery 时增加 tidyverse API OAuth 令牌过期前的时间?

use*_*745 9 r google-bigquery bigrquery tidyverse-api gargle

使用从bigrqueryř中,tidyverse API请求进行认证,其中,一旦提供,允许从R会话访问大量查询。下载结果可能很耗时,如果 oauth 令牌在传输中到期,则下载失败:

错误:凭据无效 [authError]

示例代码

# install.packages("tidyverse"); install.packages('bigrquery')
Sys.setenv(BIGQUERY_TEST_PROJECT="your-gcp-project-id") 
library(tidyverse)
library(dbplyr)
library(bigrquery)

billing <- bq_test_project()

connection <- dbConnect(
  bigrquery::bigquery(),
  project = "your-gcp-project-id",
  dataset = "dataset-name",
  billing = billing
)

mytable <- tbl(connection, "mytable")

mytable %>%
  -- some heavy dplyr wrangling --
  %>% collect()
Run Code Online (Sandbox Code Playgroud)

哪个返回

Running job [/] 20s
Complete
Billed 400GB
Downloading 230,000,000 rows
Downloading data [=====--------] 28% ETA: 24h
Run Code Online (Sandbox Code Playgroud)

但过了一段时间

Error: Invalid Credentials [authError]
Run Code Online (Sandbox Code Playgroud)

如何增加 0Auth 令牌到期前的时间长度?

Sim*_*.A. 2

这不是一个完整的答案,而是迄今为止我研究的细节,以防止人们重蹈我的覆辙。

超时似乎无法通过 dbplyr 控制

  • dbconnect接受驱动程序和传递给驱动程序的参数(文档dbConnect(drv, ...):。
  • 对于某些连接类型,附加参数可以包括timeout本期有一个使用 Cassandra 的示例:con <- dbConnect(odbc::odbc(), "Cassandra (DSN)", timeout = 10)
  • 但是,似乎不支持将超时作为 的参数bigquery。该文档列出了以下参数 ( projectdatasetbillingpage_sizequietuse_legacy_sqlbigint) 并指出其他参数当前被忽略。

因此,考虑到上述情况,超时似乎不太可能由 R 通过dbplyrDBI连接来控制。

将查询拆分为多个较短的查询

虽然不是 OP 的偏好(评论已经明确),但这仍然是一个潜在的解决方案。我使用基于唯一 ID 列的过滤方法,并使用包装函数来减少一些额外的混乱:

reconnect <- function(jj){
  if(exists("connection"))
    dbDisconnect(connection) # avoids multiple concurrent connections

  print(paste0(as.character(Sys.time()),"-- modulo ",jj," begun")) # track progress

  connection <- dbConnect(
    bigrquery::bigquery(),
    project = "your-gcp-project-id",
    dataset = "dataset-name",
    billing = billing
  )

  mytable <- tbl(connection, "mytable") %>%
    filter(unique_id %% NUM_SUBSETS == jj) # filter to subset, requires unique_id

  # assignment into the parent environment
  assign("connection", connection, envir = parent.frame())
  assign("mytable ", mytable , envir = parent.frame())
}
Run Code Online (Sandbox Code Playgroud)

然后我们迭代如下:

## parameters
DEVELOPMENT_MODE = FALSE
NUM_SUBSETS = 50

## subset
modulo = if(DEVELOPMENT_MODE){ modulo = 0 # only one if development mode
} else { modulo = 0:(NUM_SUBSETS-1) # otherwise all of them
}

results = data.frame()

for(jj in modulo){
  reconnect(jj)

  these_results = mytable %>%
    -- some heavy dplyr wrangling --
    %>% collect()

  results = rbind(results, these_results)
}
Run Code Online (Sandbox Code Playgroud)

DEVELOPER_MODE在测试/开发时设置为 true,当我希望整个过程运行时设置为 false。

其他需要考虑的途径

  • 检查是否可以在bigquery帐户内设置/控制超时(如果无法通过R控制)。
  • 调查有多复杂-- heavy dplyr wrangling here --。因为 dbplyr 不能转换非常高效的 SQL 代码,所以在我在 SQL Server 上的工作中,保存中间表已经减少了我的运行时间。鉴于下载 10GB 的速度应该比几个小时快得多,瓶颈可能是 bigquery 即时执行所有争论(并且最初的 20 秒执行是惰性评估)。链接表明单次执行的持续时间有六小时的限制。