sábado, 3 de agosto de 2024

GCP: Cargar y exportar datos en BigQuery


GCP BigQuery nos permite tanto cargar como exportar datos. Los formatos de los archivos pueden ser TXT o CSV generalmente.

Si queremos exportar datos de una tabla a un archivo CSV podríamos hacer los siguiente.

Abrimos la consola de GCP y en el editor de consultas colocamos:

EXPORT DATA
  OPTIONS (
    uri = 'gs://bucket/folder/pesos*.csv',
    format = 'CSV',
    overwrite = true,
    header = true,
    field_delimiter = ';')
AS (
  SELECT fecha, valor
  FROM mydataset.pesos
  ORDER BY fecha
);

Como se puede ver:

  1. Colocamos la ubicación de nuestro Bucket.
  2. Seteamos el formato del archivo, en este caso será un CSV.
  3. El archivo será sobreescrito.
  4. El delimitardor será un punto y coma (;).

Una vez que el comando es ejecutado desde el editor de consultas GCP, debemos uicarnos en el directorio y descargar el archivo CSV generado.

Si queremos complicarnos la vida, podríamos crear un programa en Java que haga exactamente los mismo.

ExtractTableToCsv.java

import com.google.cloud.RetryOption;
import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.Job;
import com.google.cloud.bigquery.Table;
import com.google.cloud.bigquery.TableId;
import org.threeten.bp.Duration;

public class ExtractTableToCsv {

  public static void runExtractTableToCsv() {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "bigquery-public-data";
    String datasetName = "samples";
    String tableName = "shakespeare";
    String bucketName = "my-bucket";
    String destinationUri = "gs://" + bucketName + "/path/to/file";
    // For more information on export formats available see:
    // https://cloud.google.com/bigquery/docs/exporting-data#export_formats_and_compression_types
    // For more information on Job see:
    // https://googleapis.dev/java/google-cloud-clients/latest/index.html?com/google/cloud/bigquery/package-summary.html

    String dataFormat = "CSV";
    extractTableToCsv(projectId, datasetName, tableName, destinationUri, dataFormat);
  }

  // Exports datasetName:tableName to destinationUri as raw CSV
  public static void extractTableToCsv(
      String projectId,
      String datasetName,
      String tableName,
      String destinationUri,
      String dataFormat) {
    try {
      // Initialize client that will be used to send requests. This client only needs to be created
      // once, and can be reused for multiple requests.
      BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();

      TableId tableId = TableId.of(projectId, datasetName, tableName);
      Table table = bigquery.getTable(tableId);

      Job job = table.extract(dataFormat, destinationUri);

      // Blocks until this job completes its execution, either failing or succeeding.
      Job completedJob =
          job.waitFor(
              RetryOption.initialRetryDelay(Duration.ofSeconds(1)),
              RetryOption.totalTimeout(Duration.ofMinutes(3)));
      if (completedJob == null) {
        System.out.println("Job not executed since it no longer exists.");
        return;
      } else if (completedJob.getStatus().getError() != null) {
        System.out.println(
            "BigQuery was unable to extract due to an error: \n" + job.getStatus().getError());
        return;
      }
      System.out.println(
          "Table export successful. Check in GCS bucket for the " + dataFormat + " file.");
    } catch (BigQueryException | InterruptedException e) {
      System.out.println("Table extraction job was interrupted. \n" + e.toString());
    }
  }
}

Ahora, ¿si queremos cargar un archivo a una determinada tabla?

Procedemos a escribir la siguiente instrucción en el editor de consultas de GCP:

LOAD DATA INTO mydataset.pesos FROM FILES(
  format = 'CSV',
  uri = ['gs://bucket/folder/123.csv','gs://bucket/folder/456.csv']
);

Donde:

  1. Definimos el formato de los archivos a cargar, en este caso son CSV.
  2. Colocamos la ubicación de los archivos de datos a cargar en la tabla (pesos).

Nota: El archivo CSV debe contener campos que concuerden con los de la tabla. En caso contrario, habrá errores a la hora de la carga.

Si queremos complicarnos la vida, podríamos crear un programa en Java que haga exactamente los mismo.

LoadCsvFromGcs.java

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.CsvOptions;
import com.google.cloud.bigquery.Field;
import com.google.cloud.bigquery.Job;
import com.google.cloud.bigquery.JobInfo;
import com.google.cloud.bigquery.LoadJobConfiguration;
import com.google.cloud.bigquery.Schema;
import com.google.cloud.bigquery.StandardSQLTypeName;
import com.google.cloud.bigquery.TableId;

// Sample to load CSV data from Cloud Storage into a new BigQuery table
public class LoadCsvFromGcs {

  public static void runLoadCsvFromGcs() throws Exception {
    // TODO(developer): Replace these variables before running the sample.
    String datasetName = "MY_DATASET_NAME";
    String tableName = "MY_TABLE_NAME";
    String sourceUri = "gs://cloud-samples-data/bigquery/us-states/us-states.csv";
    Schema schema =
        Schema.of(
            Field.of("name", StandardSQLTypeName.STRING),
            Field.of("post_abbr", StandardSQLTypeName.STRING));
    loadCsvFromGcs(datasetName, tableName, sourceUri, schema);
  }

  public static void loadCsvFromGcs(
      String datasetName, String tableName, String sourceUri, Schema schema) {
    try {
      // Initialize client that will be used to send requests. This client only needs to be created
      // once, and can be reused for multiple requests.
      BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();

      // Skip header row in the file.
      CsvOptions csvOptions = CsvOptions.newBuilder().setSkipLeadingRows(1).build();

      TableId tableId = TableId.of(datasetName, tableName);
      LoadJobConfiguration loadConfig =
          LoadJobConfiguration.newBuilder(tableId, sourceUri, csvOptions).setSchema(schema).build();

      // Load data from a GCS CSV file into the table
      Job job = bigquery.create(JobInfo.of(loadConfig));
      // Blocks until this load table job completes its execution, either failing or succeeding.
      job = job.waitFor();
      if (job.isDone()) {
        System.out.println("CSV from GCS successfully added during load append job");
      } else {
        System.out.println(
            "BigQuery was unable to load into the table due to an error:"
                + job.getStatus().getError());
      }
    } catch (BigQueryException | InterruptedException e) {
      System.out.println("Column not added during load append \n" + e.toString());
    }
  }
}

Nota: El código se tomó de la página oficial de GCP. Tu lo puedes editar a tu conveniencia.

Hemos visto como cargar y exportar datos a tablas en BigQuery.

Enlaces:

https://cloud.google.com/bigquery/docs/exporting-data
https://cloud.google.com/bigquery/docs/loading-data-cloud-storage-csv

No hay comentarios:

Publicar un comentario