9

使用 R中的 bigrquery 时,tidyverse API 会要求进行身份验证,一旦提供身份验证,就可以从 R 会话访问 bigquery。下载结果可能很耗时,如果 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()

哪个返回

Running job [/] 20s
Complete
Billed 400GB
Downloading 230,000,000 rows
Downloading data [=====--------] 28% ETA: 24h

但过了一段时间

Error: Invalid Credentials [authError]

问题

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

4

2 回答 2

3

我也有同样的错误,我得到了问题的超时。

另一个潜在的解决方案是导出到谷歌数据工作室,然后通过 csv 下载它作为一种解决方法。

或者对于大型数据集,最好通过将 BigQuery 结果提取到 Google Cloud Storage,然后根据本文从那里下载数据来完成: https ://mran.microsoft.com/web/packages/bigQueryR/vignettes/bigQueryR .html

    ## Create the data extract from BigQuery to Cloud Storage
    job_extract <- bqr_extract_data("your_project",
                                    "your_dataset",
                                    "bigResultTable",
                                    "your_cloud_storage_bucket_name")

    ## poll the extract job to check its status
    ## its done when job$status$state == "DONE"
    bqr_get_job("your_project", job_extract$jobReference$jobId)

    ## to download via a URL and not logging in via Google Cloud Storage interface:
    ## Use an email that is Google account enabled
    ## Requires scopes:
    ##  https://www.googleapis.com/auth/devstorage.full_control
    ##  https://www.googleapis.com/auth/cloud-platform
    ## set via options("bigQueryR.scopes") and reauthenticate if needed

    download_url <- bqr_grant_extract_access(job_extract, "your@email.com")

    ## download_url may be multiple if the data is > 1GB
    > [1] "https://storage.cloud.google.com/big-query-r-extracts/extract-20160311112410-000000000000.csv"
    > [2] "https://storage.cloud.google.com/big-query-r-extracts/extract-20160311112410-000000000001.csv"
    > [3] "https://storage.cloud.google.com/big-query-r-extracts/extract-20160311112410-000000000002.csv"
于 2020-05-13T08:37:08.463 回答
2

不是一个完整的答案,而是我迄今为止的研究细节,以防止人们追溯我的步骤。

超时似乎无法通过 dbplyr 控制

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

dbplyr因此,鉴于上述情况, R viaDBI或连接似乎不太可能控制超时。

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

虽然不是 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())
}

然后我们迭代如下:

## 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)
}

DEVELOPER_MODE在测试/开发时设置为 true,当我想要整个运行时设置为 false。

其他需要考虑的途径

  • 检查是否可以在 bigquery 帐户中设置/控制超时(如果不能通过 R 控制)。
  • 调查有多复杂-- heavy dplyr wrangling here --。因为 dbplyr 不能翻译非常高效的 sql 代码,所以在我的 SQL 服务器工作中,保存中间表已经缩短了我的运行时间。鉴于下载 10GB 应该比几个小时快得多,瓶颈可能是 bigquery 执行所有动态处理(并且最初的 20 秒执行是延迟评估)。链接表明单次执行的持续时间有六小时限制。
于 2020-05-11T04:13:25.677 回答