Quand en utilisant bigrquery de R , l'API tidyverse demande une authentification, qui, une fois fournie, permet d'accéder à bigquery depuis la session R. Le téléchargement des résultats peut prendre du temps, et si le jeton oauth expire au milieu du transfert, le téléchargement échoue:
Erreur: informations d'identification non valides [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()
Quels retours
Running job [/] 20s
Complete
Billed 400GB
Downloading 230,000,000 rows
Downloading data [=====--------] 28% ETA: 24h
mais après un certain temps
Error: Invalid Credentials [authError]
Comment la durée avant l'expiration du jeton 0Auth peut-elle être augmentée?
Pas une réponse complète, mais les détails de mes recherches jusqu'à présent pour éviter aux gens de revenir sur mes pas.
dbconnect
accepte à la fois le pilote et les arguments à transmettre au pilote ( documentation ): dbConnect(drv, ...)
.timeout
. Ce problème a un exemple utilisant Cassandra: con <- dbConnect(odbc::odbc(), "Cassandra (DSN)", timeout = 10)
.bigquery
. La documentation liste les arguments suivants (project
, dataset
, billing
, page_size
, quiet
, use_legacy_sql
, bigint
) et note que les autres arguments sont actuellement ignorés.Compte tenu de ce qui précède, il semble peu probable que le délai d'expiration puisse être contrôlé par R via dbplyr
, DBI
ou la connexion.
Bien que ce ne soit pas une préférence de OP (les commentaires le précisent), il s'agit toujours d'une solution potentielle. J'utilise une approche de filtrage basée sur une colonne d'identifiant unique, avec une fonction wrapper pour réduire une partie de l'encombrement supplémentaire:
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())
}
On itère ensuite comme suit:
## 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)
}
J'ai mis DEVELOPER_MODE
à true lors du test/développement et à false lorsque je veux que tout fonctionne.
-- heavy dplyr wrangling here --
est. Étant donné que dbplyr ne traduit pas de code SQL très efficace, dans mon travail sur le serveur SQL, la sauvegarde de tables intermédiaires a réduit les heures d'exécution. Étant donné que le téléchargement de 10 Go devrait être beaucoup plus rapide que plusieurs heures, le goulot d'étranglement pourrait être une grosse requête conduisant toutes les disputes à la volée (et que l'exécution initiale de 20 secondes se fait avec une évaluation paresseuse). This lien suggère qu'il y a une limite de six heures sur la durée d'une seule exécution.