web-dev-qa-db-ja.com

Google Cloud Storageを使用せずにBigQueryデータをCSVにエクスポートする

現在、大量のBigQueryデータをエクスポートし、クエリした結果をCSVファイルとしてローカルに保存するソフトウェアを作成しています。私はPython 3とGoogleが提供するクライアントを使用しました。構成と認証を行いましたが、問題は、データをローカルに保存できないことです。実行するたびに、次のようになります- エラーメッセージ

googleapiclient.errors.HttpError:https://www.googleapis.com/bigquery/v2/projects/round-office-769/jobs?alt=jsonが "無効な抽出先URI 'response/file-name-*。csv'を返しました。有効なGoogleストレージパスである必要があります。 ">

これは私のジョブ設定です:

def export_table(service, cloud_storage_path,
             projectId, datasetId, tableId, sqlQuery,
             export_format="CSV",
             num_retries=5):

# Generate a unique job_id so retries
# don't accidentally duplicate export
job_data = {
    'jobReference': {
        'projectId': projectId,
        'jobId': str(uuid.uuid4())
    },
    'configuration': {
        'extract': {
            'sourceTable': {
                'projectId': projectId,
                'datasetId': datasetId,
                'tableId': tableId,
            },
            'destinationUris': ['response/file-name-*.csv'],
            'destinationFormat': export_format
        },
        'query': {
            'query': sqlQuery,
        }
    }
}
return service.jobs().insert(
    projectId=projectId,
    body=job_data).execute(num_retries=num_retries)

クラウドストレージの代わりにローカルパスを使用してデータを保存できるといいのですが、それは間違っていました。

だから私の質問は:

クエリされたデータをローカル(またはローカルデータベース)にダウンロードできますか、それともGoogle Cloud Storageを使用する必要がありますか?

14
mkjoerg

エクスポートジョブにはGoogle Cloud Storageを使用する必要があります。 BigQueryからのデータのエクスポートについて説明します こちら 。さまざまなパス構文のバリアントも確認してください。

次に、GCSからローカルストレージにファイルをダウンロードできます。

Gsutil ツールを使用すると、GCSからローカルマシンにファイルをさらにダウンロードできます。

ローカルに1回の移動でダウンロードすることはできません。ローカルマシンに転送するよりも、まずGCSにエクスポートする必要があります。

12
Pentium10

ページングメカニズムを使用して、すべてのデータを直接(Google Cloud Storage経由でルーティングせずに)ダウンロードできます。基本的には、ページごとにページトークンを生成し、ページ内のデータをダウンロードして、すべてのデータがダウンロードされるまで、つまり、トークンが使用できなくなるまでこれを繰り返す必要があります。 Javaのコード例を以下に示します。うまくいけばアイデアが明確になります。

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.bigquery.Bigquery;
import com.google.api.services.bigquery.BigqueryScopes;
import com.google.api.client.util.Data;
import com.google.api.services.bigquery.model.*;

/* your class starts here */

private String projectId = ""; /* fill in the project id here */
private String query = ""; /* enter your query here */
private Bigquery bigQuery;
private Job insert;
private TableDataList tableDataList;
private Iterator<TableRow> rowsIterator;
private List<TableRow> rows;
private long maxResults = 100000L; /* max number of rows in a page */

/* run query */
public void open() throws Exception {
    HttpTransport transport = GoogleNetHttpTransport.newTrustedTransport();
    JsonFactory jsonFactory = new JacksonFactory();
    GoogleCredential credential = GoogleCredential.getApplicationDefault(transport, jsonFactory);
    if (credential.createScopedRequired())
        credential = credential.createScoped(BigqueryScopes.all());
    bigQuery = new Bigquery.Builder(transport, jsonFactory, credential).setApplicationName("my app").build();

    JobConfigurationQuery queryConfig = new JobConfigurationQuery().setQuery(query);
    JobConfiguration jobConfig = new JobConfiguration().setQuery(queryConfig);
    Job job = new Job().setConfiguration(jobConfig);
    insert = bigQuery.jobs().insert(projectId, job).execute();
    JobReference jobReference = insert.getJobReference();

    while (true) {
        Job poll = bigQuery.jobs().get(projectId, jobReference.getJobId()).execute();
        String state = poll.getStatus().getState();
        if ("DONE".equals(state)) {
            ErrorProto errorResult = poll.getStatus().getErrorResult();
            if (errorResult != null)
                throw new Exception("Error running job: " + poll.getStatus().getErrors().get(0));
            break;
        }
        Thread.sleep(10000);
    }

    tableDataList = getPage();
    rows = tableDataList.getRows();
    rowsIterator = rows != null ? rows.iterator() : null;
}

/* read data row by row */
public /* your data object here */ read() throws Exception {
    if (rowsIterator == null) return null;

    if (!rowsIterator.hasNext()) {
        String pageToken = tableDataList.getPageToken();
        if (pageToken == null) return null;
        tableDataList = getPage(pageToken);
        rows = tableDataList.getRows();
        if (rows == null) return null;
        rowsIterator = rows.iterator();
    }

    TableRow row = rowsIterator.next();
    for (TableCell cell : row.getF()) {
        Object value = cell.getV();
        /* extract the data here */
    }

    /* return the data */
}

private TableDataList getPage() throws IOException {
    return getPage(null);
}

private TableDataList getPage(String pageToken) throws IOException {
    TableReference sourceTable = insert
            .getConfiguration()
            .getQuery()
            .getDestinationTable();
    if (sourceTable == null)
        throw new IllegalArgumentException("Source table not available. Please check the query syntax.");
    return bigQuery.tabledata()
            .list(projectId, sourceTable.getDatasetId(), sourceTable.getTableId())
            .setPageToken(pageToken)
            .setMaxResults(maxResults)
            .execute();
}
6
jvj

そのテーブルでtabledata.list()オペレーションを実行し、「alt = csv」を設定すると、テーブルの先頭がCSVとして返されます。

3
yiru

Google BigQuery APIとpandasおよびpandas.ioをインストールすると、Jupyterノートブック内でPythonを実行し、BQテーブルにクエリを実行して、データを取得できますローカルのデータフレームに、そこからCSVに書き出すことができます。

2
Mark Ginsburg

Mikhail Berlyant が言ったように、

BigQueryには、クエリ結果をGCSまたはローカルファイルに直接エクスポート/ダウンロードする機能はありません。

まだ3つのステップでWeb UIを使用してエクスポートできます

  1. 結果をBigQueryテーブルに保存して実行するようにクエリを構成します。
  2. テーブルをGCSのバケットにエクスポートします。
  3. バケットからダウンロードします。

コストを低く抑えるには、コンテンツをGCSにエクスポートしたらテーブルを削除し、ファイルをマシンにダウンロードしたらバケットとバケットからコンテンツを削除してください。

ステップ1

BigQuery画面で、クエリを実行する前に、[その他]> [クエリ設定]に移動します

Configure Query

これは以下を開きます

Query Settings

ここにあなたがしたいです

  • 宛先:クエリ結果の宛先テーブルを設定します
  • プロジェクト名:プロジェクトを選択します。
  • データセット名:データセットを選択します。持っていない場合は、作成して戻ってください。
  • テーブル名:任意の名前を付けます(文字、数字、またはアンダースコアのみを含める必要があります)。
  • 結果サイズ:大きな結果を許可します(サイズ制限なし)。

次にそれを保存すると、クエリが特定のテーブルに保存されるように構成されます。これでクエリを実行できます。

ステップ2

これをGCPにエクスポートするには、テーブルに移動して、[エクスポート]> [GCSにエクスポート]をクリックする必要があります。

BigQuery export table

次の画面が開きます

Export to GCS

Select GCS locationで、バケット、フォルダ、ファイルを定義します。

たとえば、daria_bucketという名前のバケットがあります。小文字、数字、ハイフン(-)、およびアンダースコア(_)のみを使用してください。ドット(。 )を使用して有効なドメイン名を形成することができます。)、ファイルをバケットのルートにtestという名前で保存する場合、書き込み(GCSの場所を選択)

daria_bucket/test.csv

ファイルが大きすぎる(1 GBを超える)場合、エラーが発生します。これを修正するには、ワイルドカードを使用してより多くのファイルに保存する必要があります。したがって、*を追加する必要があります。

daria_bucket/test*.csv

Wildcard export to GCS

これにより、バケットdaria_bucket内で、テーブルから抽出されたすべてのデータがtest000000000000、test000000000001、test000000000002、... testXという名前の複数のファイルに保存されます。

ステップ3

次に、ストレージに移動すると、バケットが表示されます。

GCS bucket

その中に入ると、1つ(または複数)のファイルが見つかります。その後、そこからダウンロードできます。

これを行う別の方法は、UIからです。クエリ結果が返されたら、[CSVとしてダウンロード]ボタンを選択できます。 enter image description here

1
Victor Mota