Cloud Bigtable é o banco de dados NoSQL wide-column do GCP. Projetado para cargas com alto throughput de escrita e latência sub-milissegundo em escala massiva: séries temporais, telemetria, IoT e analytics de eventos.

É a implementação gerenciada do paper “Bigtable: A Distributed Storage System for Structured Data” (Google, 2006) e a tecnologia por trás do Google Search, Google Analytics e Gmail.

Quando usar Bigtable

Use BigtableNão use
> 1 TB de dados, > 100k ops/sDados analíticos ad-hoc (use gcp-bigquery)
Séries temporais, telemetria, IoTTransações ACID (use gcp-spanner ou gcp-cloud-sql)
Latência P99 < 10ms em leitura/escritaDocumentos hierárquicos (use gcp-firestore)
Compatibilidade com HBase APIDataset < 1 TB (custo não justificado)

Modelo de dados

Bigtable é uma tabela ordenada por row key. Não há colunas fixas: cada linha pode ter células em qualquer coluna dentro de uma família:

Row Key            | familia:coluna_a | familia:coluna_b | metricas:temp
-------------------|------------------|------------------|-------------
device#001#ts_inv  | 23.5 @ ts3       | OK @ ts3         |
                   | 22.1 @ ts2       |                  |
device#002#ts_inv  | 19.8 @ ts1       | OK @ ts1         | 19.8 @ ts1
  • Row Key: string arbitrária, único índice disponível, determina ordem e distribuição
  • Column Family: grupo de colunas com política de garbage collection compartilhada (ex: cf, metrics)
  • Cell: interseção de linha + coluna, pode ter múltiplas versões por timestamp
  • Timestamp: versão da célula (tempo real ou lógico), usada para versionamento e GC

Design de row key (crítico)

O row key é o único índice disponível. Queries ineficientes surgem de row keys mal projetados. Hotspots surgem quando muitas escritas vão para o mesmo nó (tablet).

Padrões recomendados

import time, hashlib
 
# Série temporal: device + timestamp invertido (mais recente vem primeiro no scan)
ts_invertido = str(2**63 - int(time.time() * 1000))
row_key = f"device#001#{ts_invertido}".encode()
 
# Hash prefix para distribuir IDs sequenciais ou UUIDs
prefix = hashlib.md5(user_id.encode()).hexdigest()[:4]
row_key = f"{prefix}#{user_id}#{event_type}".encode()
 
# Domínio invertido (distribui melhor do que domínio direto)
# "google.com/path" → "com.google#path"
row_key = f"com.google#/path/to/page".encode()

Antipadrões de row key

# Ruim: timestamp crescente como prefixo → hotspot no split mais recente
"2026-05-05T10:00:00#evento-id"

# Ruim: domínio popular como prefixo → hotspot em "google.com"
"google.com/..."

# Ruim: ID sequencial sem hash → hotspot crescente
"0001", "0002", "0003", ...

Instância e clusters

# Instância de produção (SSD, 3 nodes)
gcloud bigtable instances create minha-instancia \
  --display-name="Produção" \
  --cluster=cluster-br \
  --cluster-zone=southamerica-east1-a \
  --cluster-num-nodes=3 \
  --cluster-storage-type=SSD
 
# Cluster adicional para replicação cross-region
gcloud bigtable clusters create cluster-us \
  --instance=minha-instancia \
  --zone=us-central1-a \
  --num-nodes=3
 
# Autoscaling de nodes
gcloud bigtable clusters update cluster-br \
  --instance=minha-instancia \
  --autoscaling-min-nodes=1 \
  --autoscaling-max-nodes=10 \
  --autoscaling-cpu-target=60

Operações com Python SDK

from google.cloud import bigtable
from google.cloud.bigtable import row_filters
import time
 
client = bigtable.Client(project="meu-projeto", admin=True)
instance = client.instance("minha-instancia")
table = instance.table("eventos")
 
# Escrita de uma célula
row_key = b"device#001#9999850000000"
row = table.direct_row(row_key)
row.set_cell(
    column_family_id="cf",
    column="temperatura",
    value=b"23.5",
    timestamp_micros=int(time.time() * 1e6)
)
row.commit()
 
# Escrita em lote (mais eficiente)
rows = []
for device_id, temp in dados:
    ts_inv = str(2**63 - int(time.time() * 1000))
    row = table.direct_row(f"device#{device_id}#{ts_inv}".encode())
    row.set_cell("cf", "temperatura", str(temp).encode())
    rows.append(row)
 
errors = table.mutate_rows(rows)
 
# Leitura por row key exato
row = table.read_row(b"device#001#9999850000000")
if row:
    cell = row.cells["cf"][b"temperatura"][0]
    print(cell.value.decode())
 
# Scan com prefix (range query eficiente)
rows = table.read_rows(
    start_key=b"device#001#",
    end_key=b"device#001$",   # "$" vem depois de "#" em ASCII
    filter_=row_filters.CellsColumnLimitFilter(1)  # apenas versão mais recente
)
for row in rows:
    print(row.row_key, row.cells)

Filtros

Bigtable tem filtros compostos aplicados no servidor, reduzindo dados transferidos:

from google.cloud.bigtable import row_filters
from datetime import datetime, timezone
 
# Filtro de timestamp (range)
time_filter = row_filters.TimestampRangeFilter(
    start=datetime(2026, 5, 1, tzinfo=timezone.utc),
    end=datetime(2026, 5, 5, tzinfo=timezone.utc)
)
 
# Filtro de valor com regex
value_filter = row_filters.ValueRegexFilter(b"^error.*")
 
# Limitar versões retornadas
version_filter = row_filters.CellsColumnLimitFilter(1)
 
# Composição: AND (chain)
chain = row_filters.RowFilterChain(filters=[time_filter, version_filter])
 
# Composição: OR (union)
union = row_filters.RowFilterUnion(filters=[filter_a, filter_b])
 
rows = table.read_rows(filter_=chain)

Column families e garbage collection

from google.cloud.bigtable import column_family
import datetime
 
# Criar tabela com políticas de GC por família
cf_versoes = column_family.MaxVersionsGCRule(3)          # manter 3 versões
cf_tempo = column_family.MaxAgeGCRule(datetime.timedelta(days=30))  # manter 30 dias
cf_uniao = column_family.GCRuleUnion([cf_versoes, cf_tempo])  # OR: apaga se qualquer regra for satisfeita
 
table.create(column_families={
    "cf": cf_versoes,
    "metricas": cf_tempo,
    "raw": cf_uniao
})

App Profiles

Controlam o roteamento de requisições para clusters (útil com replicação):

# Routing distribuído (eventually consistent, maior disponibilidade)
gcloud bigtable app-profiles create perfil-leitura \
  --instance=minha-instancia \
  --route-any
 
# Routing para cluster específico (consistência forte)
gcloud bigtable app-profiles create perfil-escrita \
  --instance=minha-instancia \
  --route-to=cluster-br

Integração com Dataflow

from apache_beam.io.gcp.bigtableio import ReadFromBigtable, WriteToBigtable
 
# Leitura
with beam.Pipeline() as p:
    rows = p | ReadFromBigtable(
        project_id="meu-projeto",
        instance_id="minha-instancia",
        table_id="eventos"
    )
    rows | beam.Map(processar_linha)

Key Visualizer

Ferramenta no console GCP que exibe mapa de calor de acesso por row key ao longo do tempo. Ferramenta principal para diagnosticar hotspots.

# Ativar Key Visualizer na instância
gcloud bigtable instances update minha-instancia \
  --enable-key-visualizer

Monitoramento

  • Cloud Monitoring: bigtable.googleapis.com/cluster/cpu_load, bigtable.googleapis.com/server/latencies
  • Key Visualizer: identifica hotspots e distribuição de carga por row key
  • Métricas por tabela e cluster no console GCP

Ver também: gcp | gcp-bigquery | gcp-dataflow | gcp-firestore | gcp-boas-praticas | db-tipos-de-bancos-de-dados | db-nosql