从本地数据源加载数据

本页面介绍如何从本地数据源加载数据。

如需查看从本地数据源加载数据的教程,请参阅:

概览

您可通过以下方式从可读数据源(例如本地机器)加载数据:

  • 使用 GCP Console 或经典版 BigQuery 网页界面
  • 使用 CLI 的 bq load 命令
  • 使用 API
  • 使用客户端库

使用 GCP Console、经典版 BigQuery 网页界面或 CLI 加载数据时,系统会自动创建加载作业。

限制

从本地数据源加载数据将受到以下限制:

  • 从本地数据源加载文件时,不支持使用通配符和逗号分隔列表。各文件必须分别加载。
  • 使用经典版 BigQuery 网页界面时,从本地数据源加载的文件不得超过 10 MB,并且所含行数必须少于 16000 行。

所需权限

如需将数据加载到 BigQuery,您至少必须具有以下权限:

  • bigquery.tables.create 权限,用于创建新表
  • bigquery.tables.updateData 权限(如果要覆盖或附加表)
  • bigquery.jobs.create 权限,用于运行加载作业

以下预定义的 Cloud IAM 角色包含 bigquery.tables.createbigquery.tables.updateData 权限:

  • bigquery.dataEditor
  • bigquery.dataOwner
  • bigquery.admin

以下预定义的 Cloud IAM 角色包含 bigquery.jobs.create 权限:

  • bigquery.user
  • bigquery.jobUser
  • bigquery.admin

此外,如果用户具有 bigquery.datasets.create 权限,则当该用户在创建数据集时,系统会为其授予该数据集的 bigquery.dataOwner 访问权限。 借助 bigquery.dataOwner 访问权限,用户可以将数据加载到数据集中的表。

如需详细了解 BigQuery 中的 Cloud IAM 角色和权限,请参阅访问权限控制

从本地数据源加载数据

如需从本地数据源加载数据,请按如下所述操作:

控制台

  1. 在 GCP Console 中打开 BigQuery 网页界面。
    转到 GCP Console

  2. 在导航面板的资源部分中,展开您的项目并选择数据集。

  3. 在窗口右侧的详细信息面板中,点击创建表。加载数据的过程与创建空表的过程相同。

    创建表

  4. 创建表页面的来源部分,执行以下操作:

    • 基于以下数据创建表部分,选择上传

      上传表

    • 选择文件下点击浏览

      浏览文件

    • 浏览到相应文件,然后点击打开。请注意,本地文件不支持使用通配符和逗号分隔列表。

    • 文件格式部分,选择 CSVJSON(以换行符分隔)AvroParquetORC

  5. 创建表页面的目标位置部分,执行以下操作:

    • 数据集名称部分,选择相应的数据集。

      查看数据集

    • 表名称字段中,输入您要在 BigQuery 中创建的表的名称。

    • 确认表类型设置为原生表

  6. 架构部分中,输入架构定义。

    • 对于 CSV 和 JSON 文件,您可以勾选自动检测选项来启用架构自动检测功能。对于其他支持的文件类型,架构信息在源数据中为自描述形式。

    • 您也可按照以下方式手动输入架构信息:

      • 点击以文本形式修改,并以 JSON 数组格式输入表架构:

      • 使用添加字段手动输入架构。

  7. 高级选项部分选择适用项,然后点击创建表。如需了解可用选项,请参阅 CSV 选项JSON 选项

经典版界面

  1. 转到 BigQuery 网页界面。
    转到 BigQuery 网页界面

  2. 在导航面板中,将鼠标悬停在数据集上,点击向下箭头图标 向下箭头图标图片,然后点击 Create new table。加载数据的过程与创建空表的过程相同。

  3. Create Table 页面的 Source Data 部分,执行以下操作:

    • Location 部分,选择 File upload,点击 Choose file,浏览到相应文件,然后点击 Open。请注意,本地文件不支持使用通配符和逗号分隔列表。
    • File format 部分,选择 (CSV)JSON(以换行符分隔)AvroParquetORC
  4. Create Table 页面的 Destination Table 部分,执行以下操作:

    • Table name 部分,选择适当的数据集,然后在表名称字段中输入要在 BigQuery 中创建的表的名称。
    • 确认 Table type 设置为 Native table
  5. Schema 部分中,输入架构定义。

    • 对于 CSV 和 JSON 文件,您可以勾选 Auto-detect 选项来启用架构自动检测功能。对于其他支持的文件类型,架构信息在源数据中为自描述形式。

      自动检测链接

    • 您也可按照以下方式手动输入架构信息:

      • 点击 Edit as text,并以 JSON 数组格式输入表架构:

        以 JSON 数组格式添加架构

      • 使用 Add Field 手动输入架构:

        使用添加字段添加架构

  6. Options 部分中选择适用项,然后点击 Create Table。如需了解可用选项,请参阅 CSV 选项JSON 选项

CLI

使用 bq load 命令、指定 source_format,并添加本地文件的路径。

(可选)添加 --location 标志并将值设置为您的位置

如果要在非默认项目中加载数据,请按照以下格式将项目 ID 添加到数据集:project_id:dataset

bq --location=location load \
--source_format=format \
project_id:dataset.table \
path_to_source \
schema

其中:

  • location 是您的位置。--location 是可选标志。例如,如果您在东京区域使用 BigQuery,则将该标志的值设置为 asia-northeast1。您可以使用 .bigqueryrc 文件设置该位置的默认值。
  • formatCSVAVROPARQUETORCNEWLINE_DELIMITED_JSON
  • project_id 是您的项目 ID。
  • dataset 是现有数据集。
  • table 是要向其中加载数据的表的名称。
  • path_to_source 是本地文件的路径。
  • schema 是有效架构。该架构可以是本地 JSON 文件,也可以作为命令的一部分以内嵌方式输入。您还可以使用 --autodetect 标志,而不是提供架构定义。

此外,您可以为用于控制 BigQuery 数据解析方式的选项添加标志。例如,您可以使用 --skip_leading_rows 标志来忽略 CSV 文件中的标题行。如需了解详情,请参阅 CSV 选项JSON 选项

示例:

以下命令将本地机器上以换行符分隔的 JSON 文件 (mydata.json) 加载到默认项目的 mydataset 中名为 mytable 的表中。架构是在名为 myschema.json 的本地架构文件中定义的。

    bq load \
    --source_format=NEWLINE_DELIMITED_JSON \
    mydataset.mytable \
    ./mydata.json \
    ./myschema.json

以下命令将本地机器上的 CSV 文件 (mydata.csv) 加载到 myotherprojectmydataset 中名为 mytable 的表中。架构采用以下格式以内嵌方式定义:field:data_type, field:data_type

    bq load \
    --source_format=CSV \
    myotherproject:mydataset.mytable \
    ./mydata.csv \
    qtr:STRING,sales:FLOAT,year:STRING

以下命令将本地机器上的 CSV 文件 (mydata.csv) 加载到默认项目的 mydataset 中名为 mytable 的表中。架构是使用架构自动检测功能定义的。

    bq load \
    --autodetect \
    --source_format=CSV \
    mydataset.mytable \
    ./mydata.csv

C#

试用此示例之前,请按照《BigQuery 快速入门:使用客户端库》中的 C# 设置说明进行操作。如需了解详情,请参阅 BigQuery C# API 参考文档

以下代码演示了如何将本地 CSV 文件加载到新的 BigQuery 表中。如需加载其他格式的本地文件,请使用 JobCreationOptions 基类中处理相应格式的更新选项类,而不是使用 UploadCsvOptions


using Google.Cloud.BigQuery.V2;
using System;
using System.IO;

public class BigQueryLoadFromFile
{
    public void LoadFromFile(
        string projectId = "your-project-id",
        string datasetId = "your_dataset_id",
        string tableId = "your_table_id",
        string filePath = "path/to/file.csv"
    )
    {
        BigQueryClient client = BigQueryClient.Create(projectId);
        // Create job configuration
        var uploadCsvOptions = new UploadCsvOptions()
        {
            SkipLeadingRows = 1,  // Skips the file headers
            Autodetect = true
        };
        using (FileStream stream = File.Open(filePath, FileMode.Open))
        {
            // Create and run job
            // Note that there are methods available for formats other than CSV
            BigQueryJob job = client.UploadCsv(
                datasetId, tableId, null, stream, uploadCsvOptions);
            job.PollUntilCompleted();  // Waits for the job to complete.
            // Display the number of rows uploaded
            BigQueryTable table = client.GetTable(datasetId, tableId);
            Console.WriteLine(
                $"Loaded {table.Resource.NumRows} rows to {table.FullyQualifiedId}");
        }
    }
}

Go

试用此示例之前,请按照《BigQuery 快速入门:使用客户端库》中的 Go 设置说明进行操作。如需了解详情,请参阅 BigQuery Go API 参考文档

以下代码演示了如何将本地 CSV 文件加载到新的 BigQuery 表中。如需加载其他格式的本地文件,请将 NewReaderSourceDataFormat 属性设置为相应的格式。

// To run this sample, you will need to create (or reuse) a context and
// an instance of the bigquery client.  For example:
// import "cloud.google.com/go/bigquery"
// ctx := context.Background()
// client, err := bigquery.NewClient(ctx, "your-project-id")
f, err := os.Open(filename)
if err != nil {
	return err
}
source := bigquery.NewReaderSource(f)
source.AutoDetect = true   // Allow BigQuery to determine schema.
source.SkipLeadingRows = 1 // CSV has a single header line.

loader := client.Dataset(datasetID).Table(tableID).LoaderFrom(source)

job, err := loader.Run(ctx)
if err != nil {
	return err
}
status, err := job.Wait(ctx)
if err != nil {
	return err
}
if err := status.Err(); err != nil {
	return err
}

Java

在尝试此示例之前,请先按照《BigQuery 快速入门:使用客户端库》中的 Java 设置说明进行操作。如需了解详情,请参阅 BigQuery Java API 参考文档

以下代码演示了如何将本地 CSV 文件加载到新的 BigQuery 表中。如需加载其他格式的本地文件,请将 FormatOptions 设置为相应的格式。

TableId tableId = TableId.of(datasetName, tableName);
WriteChannelConfiguration writeChannelConfiguration =
    WriteChannelConfiguration.newBuilder(tableId).setFormatOptions(FormatOptions.csv()).build();
// The location must be specified; other fields can be auto-detected.
JobId jobId = JobId.newBuilder().setLocation(location).build();
TableDataWriteChannel writer = bigquery.writer(jobId, writeChannelConfiguration);
// Write data to writer
try (OutputStream stream = Channels.newOutputStream(writer)) {
  Files.copy(csvPath, stream);
}
// Get load job
Job job = writer.getJob();
job = job.waitFor();
LoadStatistics stats = job.getStatistics();
return stats.getOutputRows();

Node.js

试用此示例之前,请按照《BigQuery 快速入门:使用客户端库》中的 Node.js 设置说明进行操作。如需了解详情,请参阅 BigQuery Node.js API 参考文档

以下代码演示了如何将本地 CSV 文件加载到新的 BigQuery 表中。如需加载其他格式的本地文件,请将 load 函数的 metadata 参数设置为相应的格式。

// Imports the Google Cloud client library
const {BigQuery} = require('@google-cloud/bigquery');
const bigquery = new BigQuery();

async function loadLocalFile() {
  // Imports a local file into a table.

  /**
   * TODO(developer): Uncomment the following lines before running the sample.
   */
  // const filename = '/path/to/file.csv';
  // const datasetId = 'my_dataset';
  // const tableId = 'my_table';

  // Load data from a local file into the table
  const [job] = await bigquery
    .dataset(datasetId)
    .table(tableId)
    .load(filename);

  console.log(`Job ${job.id} completed.`);

  // Check the job's status for errors
  const errors = job.status.errors;
  if (errors && errors.length > 0) {
    throw errors;
  }
}

PHP

试用此示例之前,请按照《BigQuery 快速入门:使用客户端库》中的 PHP 设置说明进行操作。如需了解详情,请参阅 BigQuery PHP API 参考文档

以下代码演示了如何将本地 CSV 文件加载到新的 BigQuery 表中。如需加载其他格式的本地文件,请将 sourceFormat 设置为相应的格式。

use Google\Cloud\BigQuery\BigQueryClient;
use Google\Cloud\Core\ExponentialBackoff;

/** Uncomment and populate these variables in your code */
// $projectId  = 'The Google project ID';
// $datasetId  = 'The BigQuery dataset ID';
// $tableId    = 'The BigQuery table ID';
// $source     = 'The path to the CSV source file to import';

// instantiate the bigquery table service
$bigQuery = new BigQueryClient([
    'projectId' => $projectId,
]);
$dataset = $bigQuery->dataset($datasetId);
$table = $dataset->table($tableId);
// create the import job
$loadConfig = $table->load(fopen($source, 'r'))->sourceFormat('CSV');

$job = $table->runJob($loadConfig);
// poll the job until it is complete
$backoff = new ExponentialBackoff(10);
$backoff->execute(function () use ($job) {
    printf('Waiting for job to complete' . PHP_EOL);
    $job->reload();
    if (!$job->isComplete()) {
        throw new Exception('Job has not yet completed', 500);
    }
});
// check if the job has errors
if (isset($job->info()['status']['errorResult'])) {
    $error = $job->info()['status']['errorResult']['message'];
    printf('Error running job: %s' . PHP_EOL, $error);
} else {
    print('Data imported successfully' . PHP_EOL);
}

Python

试用此示例之前,请按照《BigQuery 快速入门:使用客户端库》中的 Python 设置说明进行操作。如需了解详情,请参阅 BigQuery Python API 参考文档

以下代码演示了如何将本地 CSV 文件加载到新的 BigQuery 表中。如需加载其他格式的本地文件,请将 LoadJobConfig.source_format 属性设置为相应的格式。

# from google.cloud import bigquery
# client = bigquery.Client()
# filename = '/path/to/file.csv'
# dataset_id = 'my_dataset'
# table_id = 'my_table'

dataset_ref = client.dataset(dataset_id)
table_ref = dataset_ref.table(table_id)
job_config = bigquery.LoadJobConfig()
job_config.source_format = bigquery.SourceFormat.CSV
job_config.skip_leading_rows = 1
job_config.autodetect = True

with open(filename, "rb") as source_file:
    job = client.load_table_from_file(source_file, table_ref, job_config=job_config)

job.result()  # Waits for table load to complete.

print("Loaded {} rows into {}:{}.".format(job.output_rows, dataset_id, table_id))

Ruby

在尝试此示例之前,请先按照《BigQuery 快速入门:使用客户端库》中的 Ruby 设置说明进行操作。如需了解详情,请参阅 BigQuery Ruby API 参考文档

以下代码演示了如何将本地 CSV 文件加载到新的 BigQuery 表中。如需加载其他格式的本地文件,请将 Table#load_job 方法的 format 参数设置为相应的格式。

require "google/cloud/bigquery"

def load_from_file(dataset_id = "your_dataset_id",
                   file_path  = "path/to/file.csv")

  bigquery = Google::Cloud::Bigquery.new
  dataset  = bigquery.dataset dataset_id
  table_id = "new_table_id"

  # Infer the config.location based on the location of the referenced dataset.
  load_job = dataset.load_job table_id, file_path do |config|
    config.skip_leading = 1
    config.autodetect   = true
  end
  load_job.wait_until_done! # Waits for table load to complete.

  table = dataset.table table_id
  puts "Loaded #{table.rows_count} rows into #{table.id}"
end

使用本地文件覆盖或附加到表

您可以通过添加来自源文件的数据或附加查询结果,将其他数据加载到表中。如果数据架构与目标表或分区的架构不匹配,您可以在执行附加或覆盖操作时更新架构。

如果您要在附加数据时更新架构,BigQuery 将允许执行以下操作:

  • 添加新字段
  • REQUIRED 字段放宽为 NULLABLE

如果要覆盖表,则总是会覆盖架构。在覆盖表时,架构更新不受限制。

在控制台或经典版 BigQuery 网页界面中,使用 Write preference 选项指定在从源文件或查询结果加载数据时要执行的操作。CLI 和 API 包括以下选项:

Console 选项 经典版界面选项 CLI 标志 BigQuery API 属性 说明
只写入空白表 Write if empty WRITE_EMPTY 仅当表为空时才写入数据。
附加到表 Append to table --noreplace--replace=false;如果未指定 --replace,则默认为附加 WRITE_APPEND (默认)在表末尾附加数据。
覆盖表 Overwrite table --replace--replace=true WRITE_TRUNCATE 清空表中所有现有数据,然后再写入新数据。

如需从本地文件加载 CSV、JSON、Avro、Parquet 或 ORC 数据并覆盖或附加到 BigQuery 表,请按如下所述操作:

控制台

  1. 在 GCP Console 中打开 BigQuery 网页界面。
    转到 GCP Console

  2. 在导航面板的资源部分中,展开您的项目并选择数据集。

  3. 在窗口右侧的详细信息面板中,点击创建表。加载数据的过程与创建空表的过程相同。

    创建表

  4. 创建表页面的来源部分,执行以下操作:

    • 基于以下数据创建表部分,选择上传

      上传表

    • 选择文件下点击浏览

      浏览文件

    • 浏览到相应文件,然后点击打开。请注意,本地文件不支持使用通配符和逗号分隔列表。

    • 文件格式部分,选择 CSVJSON(以换行符分隔)AvroParquetORC

  5. 创建表页面的目标位置部分,执行以下操作:

    • 数据集名称部分,选择相应的数据集。

      选择数据集

    • 表名称字段中,输入您要在 BigQuery 中创建的表的名称。

    • 确认表类型设置为原生表

  6. 架构部分中,输入架构定义。

    • 对于 CSV 和 JSON 文件,您可以勾选自动检测选项来启用架构自动检测功能。对于其他支持的文件类型,架构信息在源数据中为自描述形式。

    • 您也可按照以下方式手动输入架构信息:

      • 点击以文本形式修改,并以 JSON 数组格式输入表架构:

      • 使用添加字段手动输入架构。

  7. 高级选项部分,为写入偏好设置选择只写入空白表附加到表覆盖表

  8. 点击创建表

经典版界面

  1. Create Table 页面的 Source Data 部分,执行以下操作:
    • Location 部分,选择 File upload,点击 Choose file,浏览到相应文件,然后点击 Open。请注意,本地文件不支持使用通配符和逗号分隔列表。
    • File format 部分,选择 (CSV)JSON(以换行符分隔)AvroParquetORC
  2. Create Table 页面的 Destination Table 部分,执行以下操作:
    • Table name 部分,选择适当的数据集,然后在表名称字段中输入您要向其中附加数据或覆盖其数据的表的名称。
    • 确认 Table type 设置为 Native table
  3. Schema 部分中,输入架构定义。如需更新架构,您可以添加新字段或将字段从 REQUIRED 更改(放宽)为 NULLABLE

    • 对于 JSON 文件,您可以勾选 Auto-detect 选项,以启用架构自动检测

      自动检测链接

    • 您也可以按照以下方式手动输入架构信息:

      • 点击 Edit as text,并以 JSON 数组格式输入表架构:

        以 JSON 数组格式添加架构

      • 使用 Add Field 手动输入架构:

        使用添加字段添加架构

  4. Options 部分,为 Write preference 选择 Write if emptyAppend to tableOverwrite table

    使用添加字段添加架构

  5. 点击 Create Table

CLI

输入带 --replace 标志的 bq load 命令可以覆盖表。使用 --noreplace 标志可将数据附加到表。如果未指定任何标志,则默认附加数据。

(可选)添加 --location 标志并将值设置为您的位置

向表附加数据或覆盖表时,可以使用 --schema_update_option 标志将目标表的架构更新为新数据的架构。以下选项可与 --schema_update_option 标志结合使用:

  • ALLOW_FIELD_ADDITION:向架构添加新字段;新字段不能为 REQUIRED
  • ALLOW_FIELD_RELAXATION:将必填字段放宽为可以为 Null;重复此选项可指定值列表
bq --location=location load \
--[no]replace \
dataset.table \
path_to_source \
schema

其中:

  • location 是您的位置。--location 是可选标志。例如,如果您在东京区域使用 BigQuery,则将该标志的值设置为 asia-northeast1。您可以使用 .bigqueryrc 文件设置该位置的默认值。
  • dataset 是现有数据集。
  • table 是要向其中加载数据的表的名称。
  • path_to_source 是本地文件的路径。请注意,本地文件不支持使用通配符和逗号分隔列表。
  • schema 是有效架构。该架构可以是本地 JSON 文件,也可以作为命令的一部分以内嵌方式输入。您还可以使用 --autodetect 标志,而不是提供架构定义。

此外,您还可以为 JSON 选项CSV 选项添加标志,以便控制 BigQuery 解析数据的方式。

示例:

以下命令可从 mydata.json 加载数据,并覆盖 mydataset 中名为 mytable 的表。架构是使用架构自动检测功能定义的。

    bq load \
    --autodetect \
    --replace \
    --source_format=NEWLINE_DELIMITED_JSON \
    mydataset.mytable \
    ./mydata.json

以下命令可从 mydata.json 加载数据,并将数据附加到 mydataset 中名为 mytable 的表。架构是使用 JSON 架构文件 myschema.json 定义的。

    bq load \
    --autodetect \
    --noreplace \
    --source_format=NEWLINE_DELIMITED_JSON \
    mydataset.mytable \
    ./mydata.json \
    ./myschema.json

以下命令可从 mydata.json 加载数据,并将数据附加到 mydataset 中名为 mytable 的表。使用了名为 myschema.json 的本地 JSON 架构文件。架构定义包含目标表中没有的新字段。

    bq load \
    --noreplace \
    --schema_update_option=ALLOW_FIELD_ADDITION \
    --source_format=NEWLINE_DELIMITED_JSON \
    mydataset.mytable \
    ./mydata.json \
    ./myschema.json

以下命令可从 mydata.csv 加载数据,并将数据附加到 mydataset 中名为 mytable 的表。使用了名为 myschema.json 的本地 JSON 架构文件。架构定义将两个 REQUIRED 字段更改(放宽)为 NULLABLE

    bq load \
    --noreplace \
    --schema_update_option=ALLOW_FIELD_RELAXATION \
    --source_format=NEWLINE_DELIMITED_JSON \
    mydataset.mytable \
    ./mydata.csv \
    ./myschema.json

API 上传

通过媒体上传功能,BigQuery API 可以将数据存储在云端并提供给服务器。用户可能需要上传照片、视频、PDF 文件、ZIP 文件等类型的数据。

上传选项

借助 BigQuery API,您可以上传特定类型的二进制数据或媒体。您可以上传的数据的具体特性,都已在任何支持媒体上传功能的方法的参考页面中指定:

  • 上传文件的大小上限:使用该方法可以存储的数据量上限。
  • 接受的媒体 MIME 类型:使用该方法可以存储的二进制数据类型。

您可通过以下任一方法发出上传请求。使用 uploadType 请求参数指定您要使用的方法。

  • 分段上传uploadType=multipart。用于快速传输较小的文件和元数据;需在同一个请求中传输相应文件以及用于描述该文件的元数据。
  • 可续传上传uploadType=resumable。用于进行可靠的传输;该方法对于传输较大的文件尤为重要。通过这种方法,您可以使用一个会话启动请求,并可以选择在其中包含元数据。对于绝大多数应用来说,这是一个很好的策略,因为该方法也适用于传输较小的文件(只不过每次上传时都要多发出一个 HTTP 请求)。

上传媒体时,您需要使用一个特殊的 URI。事实上,所有支持媒体上传功能的方法都具有以下两个 URI 端点:

  • /upload URI,用于媒体。 上传端点的格式为带有“/upload”前缀的标准资源 URI。您可以在传输媒体数据本身时使用此 URI。示例:POST /upload/bigquery/v2/projects/projectId/jobs
  • 标准资源 URI,用于元数据。 如果资源中包含任何数据字段,那么这些字段将会用于存储对上传文件进行描述的元数据。您可以在创建或更新元数据值时使用此 URI。示例:POST /bigquery/v2/projects/projectId/jobs

分段上传

如果您有要随上传的数据一起发送的元数据,则可以发出一个 multipart/related 请求。如果您要发送的数据小到能够在连接失败时再次完整上传,那么该方法便是您的理想之选。

如需使用分段上传,请向方法的 /upload URI 发出 POST 请求,并添加查询参数 uploadType=multipart,例如:

POST https://www.googleapis.com/upload/bigquery/v2/projects/projectId/jobs?uploadType=multipart

发出分段上传请求时要使用的顶级 HTTP 标头包含:

  • Content-Type。将此项设为 multipart/related,并在其中添加您要用于标识请求各个部分的定界字符串。
  • Content-Length。将此项设为请求正文中的字节总数。该请求的媒体部分必须小于为该方法指定的文件大小上限。

该请求的正文采用 multipart/related 内容类型 [RFC2387] 的格式,且恰好包含两个部分。这两个部分由定界字符串标识,最后的定界字符串后跟两个连字符。

分段请求的每个部分都需要附加一个 Content-Type 标头:

  1. 元数据部分:必须位于第一部分,且 Content-Type 必须与该方法接受的某一元数据格式匹配。
  2. 媒体部分:必须位于第二部分,且 Content-Type 必须与该方法接受的某一媒体 MIME 类型匹配。

请查看 API 参考,在各方法的列表中了解其接受的媒体 MIME 类型以及上传文件的大小限制。

注意:如需仅创建或更新元数据部分,而不上传关联数据,只需向标准资源端点发送 POSTPUT 请求:https://www.googleapis.com/bigquery/v2/projects/projectId/jobs

示例:分段上传

以下示例展示了 BigQuery API 的分段上传请求。

POST /upload/bigquery/v2/projects/projectId/jobs?uploadType=multipart HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer your_auth_token
Content-Type: multipart/related; boundary=foo_bar_baz
Content-Length: number_of_bytes_in_entire_request_body

--foo_bar_baz
Content-Type: application/json; charset=UTF-8

{
  "configuration": {
    "load": {
      "sourceFormat": "NEWLINE_DELIMITED_JSON",
      "schema": {
        "fields": [
          {"name": "f1", "type": "STRING"},
          {"name": "f2", "type": "INTEGER"}
        ]
      },
      "destinationTable": {
        "projectId": "projectId",
        "datasetId": "datasetId",
        "tableId": "tableId"
      }
    }
  }
}

--foo_bar_baz
Content-Type: */*

CSV, JSON, AVRO, PARQUET, or ORC data
--foo_bar_baz--

如果请求成功,服务器将返回 HTTP 200 OK 状态代码以及所有元数据:

HTTP/1.1 200
Content-Type: application/json

{
  "configuration": {
    "load": {
      "sourceFormat": "NEWLINE_DELIMITED_JSON",
      "schema": {
        "fields": [
          {"name": "f1", "type": "STRING"},
          {"name": "f2", "type": "INTEGER"}
        ]
      },
      "destinationTable": {
        "projectId": "projectId",
        "datasetId": "datasetId",
        "tableId": "tableId"
      }
    }
  }
}

可续传上传

若要更可靠地上传数据文件,您可以使用可续传上传协议。利用该协议,您可以在因通信故障导致数据流中断之后恢复上传操作。如果您要传输大型文件,或者发生网络中断或某些其他传输故障的几率较高(例如,通过移动客户端应用上传时),您会发现该协议特别实用。此外,它还可以在发生网络故障时减少您的带宽使用量,因为您不必从头开始重新上传大型文件。

如需使用可续传上传,请按以下步骤操作:

  1. 启动可续传会话。向包含元数据(如果有)的上传 URI 发出初始请求。
  2. 保存可续传会话 URI。保存初始请求的响应中返回的会话 URI;您将会在此会话的后续请求中用到此 URI。
  3. 上传文件。将媒体文件发送到可续传会话 URI。

此外,使用可续传上传的应用需要通过代码来恢复中断的上传。如果上传被中断,请查看已成功接收了多少数据量,然后从该中断处恢复上传。

注意:上传 URI 的有效期为一周。

第 1 步:启动可续传会话

如需启动可续传上传,请向方法的 /upload URI 发出 POST 请求,并添加查询参数 uploadType=resumable,例如:

POST https://www.googleapis.com/upload/bigquery/v2/projects/projectId/jobs?uploadType=resumable

对于此启动请求,其正文不是为空就是仅包含元数据;您将在后续请求中传输要上传的文件的实际内容。

请在初始请求中使用以下 HTTP 标头:

  • X-Upload-Content-Type。将此项设为要在后续请求中传输的上传数据的媒体 MIME 类型。
  • X-Upload-Content-Length。将此项设为要在后续请求中传输的上传数据的字节数。在发起此请求时,如果内容长度未知,那么您可以忽略此标头。
  • Content-Type(如果提供了元数据)。根据元数据的数据类型进行设置。
  • Content-Length。将此项设为该初始请求的正文中提供的字节数。如果您采用的是分块传输编码,则不需要进行此操作。

请查看 API 参考,在各方法的列表中了解其接受的媒体 MIME 类型以及上传文件的大小限制。

示例:可续传会话的启动请求

以下示例展示了如何启动 BigQuery API 的可续传会话。

POST /upload/bigquery/v2/projects/projectId/jobs?uploadType=resumable HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer your_auth_token
Content-Length: 38
Content-Type: application/json; charset=UTF-8
X-Upload-Content-Type: */*
X-Upload-Content-Length: 2000000

{
  "configuration": {
    "load": {
      "sourceFormat": "NEWLINE_DELIMITED_JSON",
      "schema": {
        "fields": [
          {"name": "f1", "type": "STRING"},
          {"name": "f2", "type": "INTEGER"}
        ]
      },
      "destinationTable": {
        "projectId": "projectId",
        "datasetId": "datasetId",
        "tableId": "tableId"
      }
    }
  }
}

注意:对于不包含元数据的初始可续传更新请求,请将请求的正文留空,并将 Content-Length 标头设置为 0

下一部分将介绍如何处理响应。

第 2 步:保存可续传会话 URI

如果会话启动请求成功,该 API 服务器将返回 200 OK HTTP 状态代码。此外,它还提供一个 Location 标头,后者用于指定您的可续传会话 URI。以下示例中显示的 Location 标头包含 upload_id 查询参数部分,它提供了要用于此会话的唯一上传 ID。

示例:可续传会话的启动响应

下面是对第 1 步中的请求的响应:

HTTP/1.1 200 OK
Location: https://www.googleapis.com/upload/bigquery/v2/projects/projectId/jobs?uploadType=resumable&upload_id=xa298sd_sdlkj2
Content-Length: 0

以上响应示例中显示的 Location 标头的值即是您将用作 HTTP 端点以上传实际文件或查询上传状态的会话 URI。

请复制并保存该会话 URI,以便在后续请求中使用。

第 3 步:上传文件

如需上传文件,请向您在上一步中获得的上传 URI 发送 PUT 请求。上传请求的格式如下所示:

PUT session_uri

发出可续传文件上传请求时要使用的 HTTP 标头包含 Content-Length。请将此项设为您要在该请求中上传的字节数(通常为上传文件大小)。

示例:可续传文件上传请求

以下是为当前示例上传整个 200 万字节 CSV、JSON、AVRO、PARQUET 或 ORC 文件的可续传请求。

PUT https://www.googleapis.com/upload/bigquery/v2/projects/projectId/jobs?uploadType=resumable&upload_id=xa298sd_sdlkj2 HTTP/1.1
Content-Length: 2000000
Content-Type: */*

bytes 0-1999999

如果请求成功,服务器将会返回 HTTP 201 Created 以及与此资源相关联的所有元数据。如果可续传会话的初始请求为 PUT(更新现有资源),则服务器将会返回成功响应 200 OK 以及与此资源相关联的所有元数据。

如果上传请求被中断,或者服务器返回了 HTTP 503 Service Unavailable 或任何其他 5xx 响应,请按照恢复中断的上传部分中列出的步骤进行操作。


分块上传文件

借助可续传上传,您可以将一个文件分成几块,然后发送一系列请求,按顺序上传每个分块。这并不是首选方法,因为发送更多请求会降低性能,所以我们一般不建议您这样做。不过,您可以使用分块来减少单个请求中传输的数据量。如果单个请求有固定的时间限制(例如某些类别的 Google App Engine 请求),那么该方法会非常实用。如果是默认情况下没有上传进度支持的旧版浏览器,该方法还可以让您提供上传进度指示。


恢复中断的上传

如果上传请求在收到响应之前被终止,或者服务器返回了 HTTP 503 Service Unavailable 响应,那么您便需要恢复中断的上传。为此,请按以下说明操作:

  1. 请求状态。 通过向上传 URI 发出空的 PUT 请求,查询相应上传的当前状态。对于该请求,HTTP 标头应包含一个 Content-Range 标头,用于表明文件中的当前位置未知。例如,如果您的文件总长度为 2000000,请将 Content-Range 设为 */2000000。如果您不知道文件的完整大小,请将 Content-Range 设为 */*

    注意:您不仅可以请求查询上传是否已被中断,还可以请求查询分块之间的状态。例如,如果您想为旧版浏览器显示上传进度指示,此请求会非常实用。

  2. 获取已上传的字节数。 处理服务器针对状态查询返回的响应。服务器会在其响应中使用 Range 标头来表明目前已收到哪些字节。例如,0-299999Range 标头表示已收到文件的前 30 万个字节。
  3. 上传剩余的数据。 最后,在您知道应从何处恢复请求后,请发送剩余的数据或当前分块。请注意,无论在何种情况下,您都需要将剩余的数据作为单独的分块进行处理。因此,在恢复上传时,您需要发送 Content-Range 标头。
示例:恢复中断的上传

1) 请求了解上传状态。

下面的请求使用 Content-Range 标头来指明 200 万字节文件中的当前位置未知。

PUT {session_uri} HTTP/1.1
Content-Length: 0
Content-Range: bytes */2000000

2) 从响应中提取目前已上传的字节数。

服务器的响应使用 Range 标头指明目前已收到文件的前 43 个字节。使用 Range 标头的上限值来确定从何处开始续传。

HTTP/1.1 308 Resume Incomplete
Content-Length: 0
Range: 0-42

注意:如果上传完毕,则状态响应可能为 201 Created200 OK。如果在所有字节上传完毕后且客户端收到服务器返回的响应之前网络连接断开,则可能发生此情况。

3) 从中断处恢复上传。

下面的请求通过发送文件中的剩余字节(从第 43 个字节开始)来恢复上传。

PUT {session_uri} HTTP/1.1
Content-Length: 1999957
Content-Range: bytes 43-1999999/2000000

bytes 43-1999999

最佳做法

在上传媒体时,了解错误处理方面的一些最佳做法很有帮助。

  • 恢复或重试由于连接中断或任何 5xx 错误而失败的上传,此类错误包括:
    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout
  • 如果在恢复或重试上传请求时收到任何 5xx 服务器错误,请使用指数退避算法策略。如果服务器发生超载,则可能会出现此类错误。在出现大量请求或网络流量拥堵期间,指数退避有助于缓解这类问题。
  • 您不应使用指数退避来处理其他类型的请求,但仍然可以重试其中的一些。重试这些请求时,请限制重试的次数。例如,为避免报告错误,您的代码可以限制为重试十次或更少。
  • 在处理可续传上传执行中的 404 Not Found 错误时,重新开始整个上传过程。

指数退避

指数退避是网络应用的标准错误处理策略,在此过程中,客户端按照不断增加的时间间隔定期重试失败的请求。如果因大量的请求或网络流量拥堵而导致服务器返回错误,指数退避策略能够很好地处理此类错误。相反,此策略并不适合处理与网络流量或响应时间无关的错误,例如授权凭据无效或找不到文件这样的错误。

如果使用得当,指数退避还能提高带宽使用效率、减少获得成功响应所需的请求数,并最大程度地提高并发环境中的请求吞吐量。

实现简单指数退避的流程如下:

  1. 向 API 发出请求。
  2. 收到 HTTP 503 响应(指示您应该重试该请求)。
  3. 等待 1 秒 + random_number_milliseconds 毫秒,然后重试该请求。
  4. 收到 HTTP 503 响应(指示您应该重试该请求)。
  5. 等待 2 秒 + random_number_milliseconds 毫秒,然后重试该请求。
  6. 收到 HTTP 503 响应(指示您应该重试该请求)。
  7. 等待 4 秒 + random_number_milliseconds 毫秒,然后重试该请求。
  8. 收到 HTTP 503 响应(指示您应该重试该请求)。
  9. 等待 8 秒 + random_number_milliseconds 毫秒,然后重试该请求。
  10. 收到 HTTP 503 响应(指示您应该重试该请求)。
  11. 等待 16 秒 + random_number_milliseconds 毫秒,然后重试该请求。
  12. 停止。报告或记录错误。

在上述流程中,random_number_milliseconds 是一个小于或等于 1000 的随机毫秒数。这是一项很有必要的机制,因为引入一个比较小的随机延迟时间有助于更均匀地分布负载,并降低服务器发生拥堵的可能性。random_number_milliseconds 的值必须在每次等待后重新定义。

注意:等待时间始终是 (2 ^ n) 秒 + random_number_milliseconds 毫秒,其中 n 是单调递增的整数,初始值为 0。整数 n 在每次迭代(每次请求)后递增 1。

该算法设置为 n 为 5 时终止。设置此上限的目的在于防止客户端无止尽地重试;在请求被视为“不可恢复的错误”之前,它使延迟总时间达到约 32 秒。重试更多次数是可以接受的,特别是在大数量上传正在进行的情况下;只需确保将重试延迟时间设置在合理的上限即可(比如说少于 1 分钟)。

此页内容是否有用?请给出您的反馈和评价:

发送以下问题的反馈:

此网页
需要帮助?请访问我们的支持页面