web-dev-qa-db-ja.com

tidyverse API OAuth bigqueryの使用時にトークンが期限切れになるまでの時間を増やしますか?

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トークンの有効期限が切れるまでの時間を長くするにはどうすればよいですか?

9
stevec

完全な答えではありませんが、人々が私のステップをたどることから救うためのこれまでの私の研究の詳細。

タイムアウトがdbplyrで制御できないように見える

  • dbconnectは、ドライバーに渡すドライバーと引数の両方を受け入れます( documentation ):dbConnect(drv, ...)
  • 一部の接続タイプでは、追加の引数にtimeoutを含めることができます。 この問題 には、Cassandraを使用した例があります:con <- dbConnect(odbc::odbc(), "Cassandra (DSN)", timeout = 10)
  • ただし、タイムアウトはbigqueryの引数としてサポートされていないようです。 documentation は、次の引数(projectdatasetbillingpage_sizequietuse_legacy_sqlbigint)と他の引数は現在無視されていることに注意してください。

したがって、上記の場合、タイムアウトがdbplyrDBIまたは接続を介してRによって制御される可能性は低いようです。

クエリを複数の短いクエリに分割する

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サーバーでの私の作業では、中間テーブルを保存することでランタイムが数時間短縮されました。 10 GBのダウンロードは数時間よりもはるかに高速であることを考えると、ボトルネックはすべてのラングリングをその場で実行するbigqueryである可能性があります(最初の20秒の実行は遅延評価で行われます)。 これ リンクは、1回の実行に6時間の制限があることを示唆しています。
2
Simon.S.A.