Criar tabelas do Apache Iceberg BigLake

Com o BigLake, é possível acessar tabelas do Iceberg com um controle de acesso mais refinado. Para isso, crie uma tabela Iceberg BigLake.

O Iceberg é um formato de tabela de código aberto compatível com tabelas de dados de escala de petabytes. A especificação aberta do Iceberg permite executar vários mecanismos de consulta em uma única cópia dos dados armazenados em um armazenamento de objetos.

Como administrador do BigQuery, é possível aplicar o controle de acesso no nível da linha e da coluna, incluindo o mascaramento de dados em tabelas. Para informações sobre como configurar o controle de acesso no nível da tabela, consulte Configurar políticas de controle de acesso. As políticas de acesso à tabela também são aplicadas quando você usa a API BigQuery Storage como fonte de dados da tabela no Dataproc e no Spark sem servidor. As tabelas do BigLake oferecem mais integrações com outros serviços do BigQuery. Para acessar uma lista completa das integrações disponíveis, consulte Introdução às tabelas do BigLake.

É possível criar tabelas do Iceberg BigLake das seguintes maneiras:

  • Com o metastore BigLake (recomendado). O BigLake Metastore é um catálogo do Iceberg personalizado. Recomendamos o método do BigLake Metastore, porque ele permite a sincronização de tabelas entre cargas de trabalho do Spark e do BigQuery. Para isso, use um procedimento armazenado do BigQuery para o Apache Spark para inicializar o BigLake Metastore e criar a tabela do Iceberg BigLake. No entanto, as atualizações de esquema ainda exigem que você execute uma consulta de atualização no BigQuery. Para acessar uma lista completa de limitações, consulte Limitações.

  • Com o arquivo de metadados JSON do Iceberg. Se você usa um arquivo de metadados JSON do Iceberg, atualize manualmente o arquivo de metadados mais recente sempre que houver uma atualização na tabela. Para evitar isso, use o BigLake Metastore. É possível usar um procedimento armazenado do BigQuery para o Apache Spark para criar tabelas do Iceberg BigLake que fazem referência a um arquivo de metadados do Iceberg.

Antes de começar

  • Ative as APIs BigQuery Connection, BigQuery Reservation e BigLake .

    Ative as APIs

  • Se você usa um procedimento armazenado para o Spark no BigQuery para criar tabelas do Iceberg BigLake, siga estas etapas:

    1. Crie uma conexão do Spark.
    2. Configure o controle de acesso para essa conexão.
  • Para armazenar os metadados e arquivos de dados da tabela do Iceberg BigLake no Cloud Storage, crie um bucket do Cloud Storage. Você precisa se conectar ao bucket do Cloud Storage para acessar arquivos de metadados. Para fazer isso, siga estas etapas:

    1. Crie uma conexão de recursos do Cloud.
    2. Configure o acesso para essa conexão.
  • Se você estiver usando o BigLake Metastore, instale o catálogo personalizado do Iceberg apropriado para o Apache Spark. Selecione a versão do catálogo personalizado que melhor corresponde à versão do Iceberg que você está usando.

    1. Iceberg 1.5.0: gs://spark-lib/biglake/biglake-catalog-iceberg1.5.0-0.1.1-with-dependencies.jar
    2. Iceberg 1.2.0: gs://spark-lib/biglake/biglake-catalog-iceberg1.2.0-0.1.1-with-dependencies.jar
    3. Iceberg 0.14.0: gs://spark-lib/biglake/biglake-catalog-iceberg0.14.0-0.1.1-with-dependencies.jar

Funções exigidas

Para garantir que o autor da chamada da API BigLake tenha as permissões necessárias para criar uma tabela do BigLake, peça ao seu administrador para conceder ao autor da chamada da API BigLake os seguintes papéis do IAM no projeto:

Para mais informações sobre como conceder papéis, consulte Gerenciar acesso.

Esses papéis predefinidos contêm as permissões necessárias para criar uma tabela do BigLake. Para conferir as permissões exatas necessárias, expanda a seção Permissões necessárias:

Permissões necessárias

As seguintes permissões são necessárias para criar uma tabela do BigLake:

  • bigquery.tables.create
  • bigquery.connections.delegate
  • bigquery.jobs.create

Seu administrador também pode conceder essas permissões ao autor da chamada da API BigLake com papéis personalizados ou outros papéis predefinidos.

Além disso, para permitir que os usuários do BigQuery consultem a tabela, a conta de serviço associada à conexão precisa ter o papel de Leitor do BigLake (roles/biglake.viewer) e acesso ao bucket do Cloud Storage que contém esses dados. de dois minutos.

Para criar tabelas do Iceberg BigLake com o metastore do BigLake, o autor da chamada da API do BigLake muda. Você precisa conceder ao Dataproc ou à conta de serviço do Spark acesso ao bucket do Cloud Storage que contém esses dados:

Criar tabelas com o BigLake Metastore

Recomendamos a criação de tabelas do Iceberg BigLake com o BigLake Metastore. É possível usar o Apache Spark para criar essas tabelas. Uma maneira conveniente de fazer isso é usar os procedimentos armazenados no BigQuery para o Spark seguindo estas etapas:

  1. Acessar a página do BigQuery.

    Ir para o BigQuery

  2. No painel Explorer, clique na conexão do projeto que você usou para criar o recurso de conexão.

  3. Para criar um procedimento armazenado para o Spark, clique em Criar procedimento armazenado.

  4. No editor de consultas, modifique o exemplo de código para inicializar o BigLake Metastore e criar uma tabela do Iceberg BigLake usando a instrução CREATE PROCEDURE que aparece:

     # Creates a stored procedure that initializes BLMS and database.
     # Creates a table in the database and populates a few rows of data.
     CREATE OR REPLACE PROCEDURE iceberg_demo.iceberg_setup_3_3 ()
     WITH CONNECTION `PROCEDURE_CONNECTION_PROJECT_ID.PROCEDURE_CONNECTION_REGION.PROCEDURE_CONNECTION_ID`
     OPTIONS(engine="SPARK",
     jar_uris=["gs://spark-lib/biglake/biglake-catalog-iceberg1.2.0-0.1.0-with-dependencies.jar"],
     properties=[
     ("spark.jars.packages","org.apache.iceberg:iceberg-spark-runtime-3.3_2.12:1.2.0"),
     ("spark.sql.catalog.CATALOG", "org.apache.iceberg.spark.SparkCatalog"),
     ("spark.sql.catalog.CATALOG.catalog-impl", "org.apache.iceberg.gcp.biglake.BigLakeCatalog"),
     ("spark.sql.catalog.CATALOG.hms_uri: HMS_URI")
     ("spark.sql.catalog.CATALOG.gcp_project", "PROJECT_ID"),
     ("spark.sql.catalog.CATALOG.gcp_location", "LOCATION"),
     ("spark.sql.catalog.CATALOG.blms_catalog", "CATALOG"),
     ("spark.sql.catalog.CATALOG.warehouse", "DATA_WAREHOUSE_URI")
     ]
     )
     LANGUAGE PYTHON AS R'''
     from pyspark.sql import SparkSession
    
     spark = SparkSession \
       .builder \
       .appName("BigLake Iceberg Example") \
       .enableHiveSupport() \
       .getOrCreate()
    
     spark.sql("CREATE NAMESPACE IF NOT EXISTS CATALOG;")
     spark.sql("CREATE DATABASE IF NOT EXISTS CATALOG.CATALOG_DB;")
     spark.sql("DROP TABLE IF EXISTS CATALOG.CATALOG_DB.CATALOG_TABLE;")
    
     /* Create a BigLake Metastore table and a BigQuery Iceberg table. */
     spark.sql("CREATE TABLE IF NOT EXISTS CATALOG.CATALOG_DB.CATALOG_TABLE (id bigint, demo_name string)
               USING iceberg
               TBLPROPERTIES(bq_table='BQ_DATASET.BQ_TABLE', bq_connection='TABLE_CONNECTION_PROJECT_ID.TABLE_CONNECTION_REGION.TABLE_CONNECTION_ID');
               ")
    
     /* Copy a Hive Metastore table to BigLake Metastore. Can be used together with
        TBLPROPERTIES `bq_table` to create a BigQuery Iceberg table. */
     spark.sql("CREATE TABLE CATALOG.CATALOG_DB.CATALOG_TABLE (id bigint, demo_name string)
                USING iceberg
                TBLPROPERTIES(hms_table='HMS_DB.HMS_TABLE');")
     ''';
    

    Substitua:

    • PROCEDURE_CONNECTION_PROJECT_ID: o projeto que contém a conexão para executar os procedimentos do Spark. Por exemplo, myproject.

    • PROCEDURE_CONNECTION_REGION: a região que contém a conexão para executar os procedimentos do Spark, por exemplo, us.

    • PROCEDURE_CONNECTION_ID: o ID da conexão. Por exemplo, myconnection.

      Quando você visualiza os detalhes da conexão no console do Google Cloud, esse é o valor na última seção do ID da conexão totalmente qualificado, mostrado em ID da conexão, por exemplo, projects/myproject/locations/connection_location/connections/myconnection.

    • CATALOG: o nome do catálogo do Iceberg a ser criado para o BigLake Metastore.

      O valor padrão é iceberg.

    • HMS_URI: se você quiser copiar tabelas do Hive Metastore para o BigLake Metastore, especifique um URI do Hive Metastore.

      Por exemplo, thrift://localhost:9083.

    • PROJECT_ID: o ID do projeto em que você quer criar a instância do BigLake Metastore.

      As tabelas Iceberg BigLake também são criadas no mesmo projeto.

    • LOCATION: o local onde você quer criar a instância do BigLake Metastore.

      O BigQuery só pode acessar as instâncias do BigLake Metastore armazenados no mesmo local.

    • DATA_WAREHOUSE_URI: o URI do bucket do Cloud Storage que você criou para armazenar os metadados e arquivos de dados do Iceberg.

      Por exemplo, gs://mybucket/iceberg-warehouse.

    • CATALOG_DB: o nome do banco de dados que você quer criar no BigLake Metastore.

      Esse banco de dados é equivalente ao conjunto de dados do BigQuery que conterá a tabela do Iceberg BigLake.

    • CATALOG_TABLE: o nome da tabela que você quer criar no BigLake Metastore.

      Essa tabela é equivalente à tabela do Iceberg BigLake que você quer criar.

    • BQ_DATASET: o conjunto de dados do BigQuery para conter a tabela do Iceberg BigLake.

    • BQ_TABLE: a tabela do Iceberg BigLake que você quer criar.

    • TABLE_CONNECTION_PROJECT_ID: o projeto que contém a conexão para criar a tabela do BigLake. Por exemplo, myproject.

    • TABLE_CONNECTION_REGION: a região que contém a conexão para criar a tabela do BigLake, por exemplo, us.

    • TABLE_CONNECTION_ID: o ID da conexão. Por exemplo, myconnection.

      Quando você visualiza os detalhes da conexão no console do Google Cloud, esse é o valor na última seção do ID da conexão totalmente qualificado, mostrado em ID da conexão, por exemplo, projects/myproject/locations/connection_location/connections/myconnection.

      A conta de serviço associada à conexão precisa ter roles/biglake.viewer para permitir que os usuários do BigQuery consultem a tabela.

    • HMS_DB: se você quiser copiar tabelas do Metastore do Hive para o BigLake Metastore, especifique um banco de dados do Metastore do Hive

    • HMS_TABLE: se você quiser copiar tabelas do Metastore do Hive para o BigLake Metastore, especifique uma tabela do Metastore do Hive

    Para informações sobre as configurações de catálogo do Iceberg, consulte Catálogos do Spark.

  5. Para executar o procedimento armazenado, clique em Executar. Para mais informações, consulte Chamar o procedimento armazenado do Spark. uma tabela Iceberg BigLake é criada no BigQuery.

Criar tabelas com um arquivo de metadados

É possível criar tabelas do Iceberg BigLake com um arquivo de metadados JSON. No entanto, esse não é o método recomendado porque você precisa atualizar manualmente o URI do arquivo de metadados JSON para manter a tabela do BigLake atualizada. Se o URI não for atualizado, as consultas no BigQuery poderão falhar ou fornecer resultados diferentes de outros mecanismos de consulta que usam diretamente um catálogo do Iceberg. Para evitar isso, defina como referência uma instância do BigLake Metastore ao criar uma tabela do Iceberg BigLake.

Os arquivos de metadados da tabela do Iceberg são criados no bucket do Cloud Storage que você especificou ao criar uma tabela do Iceberg usando o Spark.

Selecione uma das seguintes opções:

SQL

Use a instrução CREATE EXTERNAL TABLE. O exemplo a seguir cria uma tabela do BigLake chamada myexternal-table:

  CREATE EXTERNAL TABLE myexternal-table
  WITH CONNECTION `myproject.us.myconnection`
  OPTIONS (
         format = 'ICEBERG',
         uris = ["gs://mybucket/mydata/mytable/metadata/iceberg.metadata.json"]
   )

Substitua o valor uris pelo arquivo de metadados JSON mais recente para um snapshot de tabela específico.

É possível ativar o filtro de partição definindo a sinalização require_partition_filter.

bq

Em um ambiente de linha de comando, use o comando bq mk --table com o decorador @connection para especificar a conexão a ser usada no final do parâmetro --external_table_definition. Para ativar o filtro de partição exigido, use --require_partition_filter.

bq mk 
--table
--external_table_definition=TABLE_FORMAT=URI@projects/CONNECTION_PROJECT_ID/locations/CONNECTION_REGION/connections/CONNECTION_ID
PROJECT_ID:DATASET.EXTERNAL_TABLE

Substitua:

  • TABLE_FORMAT: o formato da tabela que você quer criar

    Nesse caso, ICEBERG.

  • URI: o arquivo de metadados JSON mais recente para um snapshot de tabela específica.

    Por exemplo, gs://mybucket/mydata/mytable/metadata/iceberg.metadata.json

  • CONNECTION_PROJECT_ID: o projeto que contém a conexão para criar a tabela do BigLake. Por exemplo, myproject

  • CONNECTION_REGION: a região que contém a conexão para criar a tabela do BigLake, por exemplo, us.

  • CONNECTION_ID: o ID da conexão da tabela. Por exemplo, myconnection.

    Quando você visualiza os detalhes da conexão no console do Google Cloud, esse é o valor na última seção do ID da conexão totalmente qualificado, mostrado em ID da conexão, por exemplo, projects/myproject/locations/connection_location/connections/myconnection.

  • DATASET: o nome do conjunto de dados do BigQuery em que você quer criar uma tabela

    Por exemplo, mydataset

  • EXTERNAL_TABLE: o nome da tabela que você quer criar.

    Por exemplo, mytable

Atualizar metadados de tabela

Se você usar um arquivo de metadados JSON para criar tabelas do Iceberg BigLake, atualize a definição da tabela para os metadados mais recentes dela. Para atualizar o esquema ou o arquivo de metadados, selecione uma das seguintes opções:

bq

  1. Crie um arquivo de definição da tabela:

    bq mkdef --source_format=ICEBERG \
    "URI" > TABLE_DEFINITION_FILE
    
  2. Use o comando bq update com a sinalização --autodetect_schema:

    bq update --autodetect_schema --external_table_definition=TABLE_DEFINITION_FILE
    PROJECT_ID:DATASET.TABLE
    

    Substitua:

    • URI: o URI do Cloud Storage com o arquivo de metadados JSON mais recente

      Por exemplo, gs://mybucket/us/iceberg/mytable/metadata/1234.metadata.json.

    • TABLE_DEFINITION_FILE: o nome do arquivo que contém o esquema da tabela

    • PROJECT_ID: o ID do projeto que contém a tabela que você quer atualizar

    • DATASET: o conjunto de dados que contém a tabela que você quer atualizar

    • TABLE: a tabela que você quer atualizar

API

Use o método tables.patch com a propriedade autodetect_schema definida como true:

PATCH https://bigquery.googleapis.com/bigquery/v2/projects/PROJECT_ID/datasets/DATASET/tables/TABLE?autodetect_schema=true

Substitua:

  • PROJECT_ID: o ID do projeto que contém a tabela que você quer atualizar
  • DATASET: o conjunto de dados que contém a tabela que você quer atualizar
  • TABLE: a tabela que você quer atualizar

No corpo da solicitação, especifique os valores atualizados dos seguintes campos:

{
     "externalDataConfiguration": {
      "sourceFormat": "ICEBERG",
      "sourceUris": [
        "URI"
      ]
    },
    "schema": null
  }'

Substitua URI pelo arquivo de metadados mais recente do Iceberg. Por exemplo, gs://mybucket/us/iceberg/mytable/metadata/1234.metadata.json.

Configurar políticas de controle de acesso

É possível usar vários métodos para controlar o acesso às tabelas do BigLake:

Por exemplo, digamos que você queira limitar o acesso à linha da tabela mytable no conjunto de dados mydataset:

+---------+---------+-------+
| country | product | price |
+---------+---------+-------+
| US      | phone   |   100 |
| JP      | tablet  |   300 |
| UK      | laptop  |   200 |
+---------+---------+-------+

É possível criar um filtro no nível da linha para Kim (kim@example.com) que restringe o acesso às linhas em que country é igual a US.

CREATE ROW ACCESS POLICY only_us_filter
ON mydataset.mytable
GRANT TO ('user:kim@example.com')
FILTER USING (country = 'US');

Em seguida, Kim executa a seguinte consulta:

SELECT * FROM projectid.mydataset.mytable;

A saída mostra apenas as linhas em que country é igual a US:

+---------+---------+-------+
| country | product | price |
+---------+---------+-------+
| US      | phone   |   100 |
+---------+---------+-------+

Consultar tabelas do BigLake

Para mais informações, consulte Consultar dados do Iceberg.

Mapeamento de dados

O BigQuery converte tipos de dados do Iceberg em tipos de dados do BigQuery, conforme mostrado na tabela a seguir:

Tipo de dados do Iceberg Tipo de dados BigQuery
boolean BOOL
int INT64
long INT64
float FLOAT64
double FLOAT64
Decimal(P/S) NUMERIC or BIG_NUMERIC depending on precision
date DATE
time TIME
timestamp DATETIME
timestamptz TIMESTAMP
string STRING
uuid BYTES
fixed(L) BYTES
binary BYTES
list<Type> ARRAY<Type>
struct STRUCT
map<KeyType, ValueType> ARRAY<Struct<key KeyType, value ValueType>>

Limitações

As tabelas do Iceberg BigLake têm limitações de tabela do BigLake, além das seguintes limitações:

  • A configuração copy-on-write é compatível, mas a configuração merge-on-read não. Para mais informações, consulte Configuração do Iceberg.

  • O BigQuery é compatível com a remoção de manifesto usando todas as funções de transformação de partição do Iceberg, exceto Bucket. Para saber mais sobre como remover partições, consulte Consultar tabelas particionadas. As consultas que fazem referência a tabelas Iceberg do BigLake precisam conter literais em predicados em comparação com colunas particionadas.

  • A criação de tabelas Iceberg BigLake na região BigQuery Omni Azure (azure-eastus2) não é compatível.

  • Somente arquivos de dados do Apache Parquet são compatíveis.

  • Todos os arquivos de dados do Iceberg precisam ter a propriedade field_id definida nos metadados para associar as colunas ao esquema do Iceberg. Tabelas com a propriedade schema.name-mapping.default não são compatíveis.

  • As tabelas do Hive migradas para as do Iceberg usando os procedimentos armazenados do Spark do Iceberg não são compatíveis.

  • Se você estiver usando o BigLake Metastore, haverá as seguintes limitações:

    • O BigLake Metastore não é compatível com as regiões do BigQuery Omni.
    • Ao renomear uma tabela, a tabela de destino precisa estar no mesmo banco de dados que a tabela de origem. O banco de dados da tabela de destino precisa ser especificado explicitamente.
    • Ao inspecionar uma tabela de metadados do Iceberg, use um nome de tabela totalmente qualificado. Por exemplo, prod.db.table.history.

Custos

A cobrança será feita por 1 TB no preço de consulta sob demanda (por TB) para cada 6.250.000 solicitações ao BigLake Metastore e para cada 625.000 objetos armazenados no BigLake Metastore. As taxas de preços de consulta sob demanda variam de acordo com a região. Para números menores de solicitações ou objetos, será cobrada a fração apropriada de 1 TB.

Por exemplo, se você fizer 6.250.000 solicitações ao BigLake Metastore e também armazenar 312.500 objetos nele, a cobrança será de 1,5 TB na taxa de preços de consulta sob demanda referente à região em que você criou a instância do BigLake Metastore.

Exigir filtro de particionamento

É possível exigir o uso de filtros de predicado ativando a opção Exigir filtro de partição para sua tabela do Iceberg. Se você ativar essa opção, as tentativas de consultar a tabela sem especificar uma cláusula WHERE que se alinha a cada arquivo de manifesto produzirão o seguinte erro:

Cannot query over table project_id.dataset.table without a
filter that can be used for partition elimination.

Cada arquivo de manifesto requer pelo menos um predicado adequado para a eliminação de partições.

É possível ativar o require_partition_filter das seguintes maneiras ao criar uma tabela Iceberg :

SQL

Use a instrução CREATE EXTERNAL TABLE.O exemplo a seguir cria uma tabela do BigLake chamada TABLE com o filtro de partição necessário ativado:

  CREATE EXTERNAL TABLE TABLE
  WITH CONNECTION `PROJECT_ID.REGION.CONNECTION_ID`
  OPTIONS (
         format = 'ICEBERG',
         uris = [URI],
         require_partition_filter = true
   )

Substitua:

  • TABLE: o nome da tabela que você quer criar.
  • PROJECT_ID: o ID do projeto que contém a tabela que você quer criar
  • REGION: o local em que você quer criar a tabela Iceberg.
  • CONNECTION_ID: o ID da conexão. Por exemplo, myconnection.

  • URI: o URI do Cloud Storage com o arquivo de metadados JSON mais recente

    Por exemplo, gs://mybucket/us/iceberg/mytable/metadata/1234.metadata.json

bq

Use o comando bq mk --table com o decorador @connection para especificar a conexão a ser usada no final do parâmetro --external_table_definition. Use --require_partition_filter para ativar o filtro de partição exigido. No exemplo a seguir, criamos uma tabela do BigLake chamada TABLE com o recurso "Exigir filtro de partição ativado":

bq mk \
    --table \
    --external_table_definition=ICEBERG=URI@projects/CONNECTION_PROJECT_ID/locations/CONNECTION_REGION/connections/CONNECTION_ID \
    PROJECT_ID:DATASET.EXTERNAL_TABLE \
    --require_partition_filter

Substitua:

  • URI: o arquivo de metadados JSON mais recente para um snapshot de tabela específica

    Por exemplo, gs://mybucket/mydata/mytable/metadata/iceberg.metadata.json.

  • CONNECTION_PROJECT_ID: o projeto que contém a conexão para criar a tabela do BigLake. Por exemplo, myproject

  • CONNECTION_REGION: a região que contém a conexão para criar a tabela do BigLake, por exemplo, us.

  • CONNECTION_ID: o ID da conexão. Por exemplo, myconnection.

    Quando você visualiza os detalhes da conexão no console do Google Cloud, esse é o valor na última seção do ID da conexão totalmente qualificado, mostrado em ID da conexão, por exemplo, projects/myproject/locations/connection_location/connections/myconnection.

  • DATASET: o nome do BigQuery

    conjunto de dados que contém a tabela que você quer atualizar. Por exemplo, mydataset

  • EXTERNAL_TABLE: o nome da tabela que você quer criar

    Por exemplo, mytable

Você também pode atualizar sua tabela do Iceberg para ativar o filtro de partição necessário.

Se você não ativar a opção Exigir filtro de partição ao criar a tabela particionada, será possível atualizá-la para adicionar a opção.

bq

Use o comando bq update e forneça a sinalização --require_partition_filter.

Exemplo:

Para atualizar mypartitionedtable em mydataset no seu projeto padrão, insira:

bq update --require_partition_filter PROJECT_ID:DATASET.TABLE

A seguir