Увеличить время до истечения срока действия токена OAuth API tidyverse при использовании bigquery? - PullRequest
9 голосов
/ 08 мая 2020

Когда использует bigrquery из R , tidyverse API запрашивает аутентификацию, которая после предоставления позволяет получить доступ к bigquery из сеанса 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()

Что возвращает

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

, но через некоторое время

Error: Invalid Credentials [authError]

Вопрос

Как можно увеличить время до истечения срока действия токена 0Auth ?

Ответы [ 2 ]

3 голосов
/ 13 мая 2020

У меня такая же ошибка, и у меня тайм-аут проблемы.

Еще одно возможное решение - экспортировать в Google Data Studio, а затем загрузить его через 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"
2 голосов
/ 11 мая 2020

Не полный ответ, но подробности моего исследования, чтобы спасти людей от повторения моих шагов.

Тайм-аут не кажется управляемым через dbplyr

  • dbconnect принимает и драйвер, и аргументы для передачи драйверу ( документация ): dbConnect(drv, ...).
  • Для некоторых типов подключения дополнительные аргументы могут включать timeout. В этой проблеме есть пример использования Cassandra: con <- dbConnect(odbc::odbc(), "Cassandra (DSN)", timeout = 10).
  • Однако тайм-аут не поддерживается в качестве аргумента для bigquery. В документации перечислены следующие аргументы (project, dataset, billing, page_size, quiet, use_legacy_sql, bigint) и отмечается, что другие аргументы в настоящее время игнорируются.

Итак, учитывая вышесказанное, маловероятно, что тайм-аут может контролироваться R через dbplyr, DBI или соединение.

Разделение запроса на несколько более коротких запросов

Хотя это не является предпочтением OP (комментарии проясняют), это все же потенциальное решение. Я использую подход фильтрации, основанный на столбце уникального идентификатора, с функцией-оболочкой, чтобы уменьшить дополнительный беспорядок:

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

I установите для DEVELOPER_MODE значение true при тестировании / разработке и значение false, если я хочу, чтобы все это работало.

Другие возможности для рассмотрения

  • Проверить, можно ли установить / контролировать время ожидания в аккаунте bigquery (если им нельзя управлять через R).
  • Исследование сложности -- heavy dplyr wrangling here --. Поскольку dbplyr не транслирует очень эффективный код sql, в моей работе над сервером SQL сохранение промежуточных таблиц сократило мои часы работы. Учитывая, что загрузка 10 ГБ должна быть намного быстрее, чем несколько часов, узким местом может быть большой запрос, выполняющий все споры на лету (и что первоначальное 20-секундное выполнение выполняется с ленивой оценкой). Эта ссылка предполагает, что продолжительность одного выполнения ограничена шестью часами.
...