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ção | Autoscale | Recursos exclusivos | SLA |
|---|---|---|---|
| Standard | Sim (sem baseline) | Sem CMEK, sem BI Engine incluso | 99.9% |
| Enterprise | Sim (com baseline reservado) | CMEK, streaming incluso | 99.99% |
| Enterprise Plus | Sim | Tudo do Enterprise + cross-region failover | 99.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-analistasProjetos sem atribuição usam on-demand automaticamente.
Storage
| Tipo | Condição | Preço (aprox.) |
|---|---|---|
| Active | Dado modificado nos últimos 90 dias | $0.02/GB/mês |
| Long-term | Dado não modificado há 90+ dias | $0.01/GB/mês (automático) |
| Physical | Opção alternativa: cobra bytes comprimidos | Varia |
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