O BigQuery cobra separadamente por compute (processamento de queries) e storage (armazenamento de dados). Entender essa separação é essencial para evitar surpresas na fatura.

Compute: on-demand vs edições

On-demand

Paga por terabyte de dados lidos pela query. Não há reserva de recursos.

  • Preço: ~$6.25 por TiB processado (varia por região)
  • O que conta como “bytes processados”: apenas as colunas lidas pela query, não a tabela inteira. BigQuery é colunar; selecionar 2 colunas de uma tabela de 100 colunas lê apenas 2%.
  • Limite padrão de 2.000 slots concorrentes por projeto
  • Ideal para cargas imprevisíveis ou times começando com BigQuery
-- Ver bytes que uma query vai processar ANTES de executar
-- (dry run via bq CLI)
bq query --dry_run --use_legacy_sql=false \
  'SELECT user_id, evento FROM `projeto.dataset.eventos` WHERE DATE(ts) = "2026-05-01"'

Edições (modelo atual para capacidade)

Lançadas em 2023, substituem o modelo flat-rate antigo. Compram-se slots (unidade de compute do BigQuery) com diferentes garantias:

EdiçãoAutoscaleRecursos exclusivosSLA
StandardSim (sem baseline)Sem CMEK, sem BI Engine incluso99.9%
EnterpriseSim (com baseline reservado)CMEK, streaming incluso99.99%
Enterprise PlusSimTudo do Enterprise + cross-region failover99.999%

Cada edição pode ser comprada com commitments de 1 ou 3 anos para desconto de até 50%.

O que é um slot

Slot é a unidade de CPU virtual do BigQuery. Uma query complexa pode usar centenas de slots em paralelo; queries simples usam poucos. No modelo on-demand, o BigQuery aloca slots automaticamente sem cobrar por eles diretamente.

graph LR
    Q[Query SQL] --> D[Dremel Engine]
    D --> S1[Slot]
    D --> S2[Slot]
    D --> S3[Slot]
    D --> S4[Slot]
    S1 --> R[Resultado]
    S2 --> R
    S3 --> R
    S4 --> R

Reservas e atribuições

Com edições, é possível criar reservas (pools de slots) e atribuições (vincular uma reserva a um projeto, pasta ou organização):

# Criar reserva de 100 slots Enterprise
bq mk --reservation \
  --project_id=meu-projeto \
  --location=US \
  --slots=100 \
  --edition=ENTERPRISE \
  minha-reserva
 
# Atribuir reserva a um projeto
bq mk --reservation_assignment \
  --project_id=meu-projeto \
  --location=US \
  --reservation_id=meu-projeto:US.minha-reserva \
  --job_type=QUERY \
  --assignee_type=PROJECT \
  --assignee_id=projeto-analistas

Projetos sem atribuição usam on-demand automaticamente.

Storage

TipoCondiçãoPreço (aprox.)
ActiveDado modificado nos últimos 90 dias$0.02/GB/mês
Long-termDado não modificado há 90+ dias$0.01/GB/mês (automático)
PhysicalOpção alternativa: cobra bytes comprimidosVaria

O BigQuery converte automaticamente tabelas de active para long-term após 90 dias sem modificação. Partições individuais também são elegíveis para long-term de forma independente.

Physical storage billing: para tabelas com alta compressão (ex: dados bem estruturados), pode ser mais barato que o billing lógico padrão. Ativar por dataset.

Monitorar custos

INFORMATION_SCHEMA

-- Top 10 queries mais caras nos últimos 7 dias
SELECT
  job_id,
  user_email,
  ROUND(total_bytes_processed / POW(1024, 4), 4) AS tib_processados,
  ROUND(total_bytes_processed / POW(1024, 4) * 6.25, 4) AS custo_usd,
  SUBSTR(query, 0, 100) AS query_resumida,
  creation_time
FROM `region-us`.INFORMATION_SCHEMA.JOBS_BY_PROJECT
WHERE
  DATE(creation_time) >= DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY)
  AND job_type = 'QUERY'
  AND state = 'DONE'
ORDER BY total_bytes_processed DESC
LIMIT 10;
 
-- Consumo por usuário
SELECT
  user_email,
  COUNT(*) AS total_queries,
  ROUND(SUM(total_bytes_processed) / POW(1024, 4), 2) AS tib_total
FROM `region-us`.INFORMATION_SCHEMA.JOBS_BY_PROJECT
WHERE DATE(creation_time) = CURRENT_DATE()
GROUP BY 1
ORDER BY 3 DESC;

Alertas de orçamento

Configurar no Cloud Billing com thresholds por % do orçamento mensal. Combinado com maximumBytesBilled nas queries críticas:

from google.cloud import bigquery
 
client     = bigquery.Client()
job_config = bigquery.QueryJobConfig(
    maximum_bytes_billed=50 * 1024**3  # rejeita queries que leriam mais de 50 GB
)
 
job = client.query("SELECT ...", job_config=job_config)

Técnicas para reduzir custos

Usar particionamento e clustering: a principal alavanca. Filtrar pela coluna de partição pode reduzir bytes lidos em 90%+. Ver gcp-bigquery-otimizacao.

Evitar SELECT *: o BigQuery cobra pelas colunas lidas. Selecionar apenas as colunas necessárias reduz diretamente o custo.

Materialized views: resultado de queries frequentes persistido e atualizado de forma incremental. Queries que se encaixam na view são reescritas automaticamente para usar o resultado materializado.

Expiração de tabelas de staging: definir expiration_ms em tabelas temporárias para evitar acúmulo de storage.

Dry run antes de executar: verificar bytes estimados antes de rodar queries exploratórias pesadas.

Ver também: gcp-bigquery | gcp-bigquery-otimizacao | gcp-bigquery-sql | gcp-boas-praticas