Lesson 1 — Cas d'usage et architecture

Un analyste qui ne fait pas exploser la facture

5 min read

This content is not translated yet. Showing the original version.

Un analyste qui ne fait pas exploser la facture

Le cas d'usage

Une équipe e-commerce pose des questions du type « quel chiffre d'affaires par catégorie en 2025 ? », « combien de commandes annulées ? ». Les données sont dans BigQuery. L'agent doit :

  1. comprendre la question et les tables ;
  2. écrire une requête GoogleSQL (le dialecte SQL de BigQuery) ;
  3. l'exécuter sans risque : ni écriture, ni table interdite, ni facture surprise ;
  4. répondre avec le résultat, la requête et une explication.

Comment BigQuery facture une requête

En tarification à la demande (on-demand), BigQuery facture les octets lus, pas le temps ni le nombre de lignes renvoyées. Et il stocke les données par colonne : il ne lit que les colonnes citées dans la requête.

RequêteCe qui est luConséquence
SELECT * FROM t LIMIT 5toutes les colonnes, toute la tableLIMIT ne réduit pas les octets facturés
SELECT id, status FROM t2 colonnes, toute la tablebeaucoup moins cher
SELECT COUNT(*) FROM tmétadonnées seulementpresque gratuit
requête sur une table partitionnée, filtrée sur la partitionseulement les partitions utilesle bon réflexe sur les grosses tables

Les tables de thelook_ecommerce sont petites (mesuré le 2026-10-15 : orders 6,8 Mo, order_items 13,6 Mo, products 4,3 Mo, events 385 Mo), ce qui en fait un terrain d'entraînement sans danger.

Un agent exécute SELECT * FROM `projet.ventes.evenements` LIMIT 10 sur une table de 500 Go. Combien d'octets sont facturés à la demande ?

Deux protections natives de BigQuery

MécanismeCe qu'il faitCoût
Dry-run (dry_run=True)BigQuery valide la requête et renvoie : type d'instruction (SELECT, DELETE…), tables lues, octets qui seraient traitésgratuit, rien n'est exécuté
maximum_bytes_billedsi la requête dépasse ce plafond, BigQuery la refuse avant de la lanceraucun : la requête échoue sans être facturée

Le dry-run sert à décider (et à expliquer au modèle pourquoi on refuse) ; maximum_bytes_billed est le filet appliqué par BigQuery lui-même si tout le reste a échoué.

sequenceDiagram
  participant M as "Gemini"
  participant C as "controle_cout"
  participant B as "BigQuery"
  M->>C: "execute_sql(SELECT * FROM order_items LIMIT 5)"
  C->>B: "dry-run"
  B-->>C: "SELECT, order_items, 13,6 Mo"
  C-->>M: "refus : trop coûteux, sélectionne moins de colonnes"
  M->>C: "execute_sql(SELECT status, COUNT(*) ...)"
  C->>B: "dry-run"
  B-->>C: "SELECT, order_items, 1,9 Mo"
  C->>B: "exécution, maximum_bytes_billed = 1 Go"
  B-->>M: "lignes"

L'architecture du lab

BriqueRôleFourni par
BigQueryToolsetoutils get_table_info et execute_sql, lecture seule, plafond, labelsADK
controle_coutdry-run, liste blanche de tables, plafond expliqué au modèlevotre code (before_tool_callback)
Gemini sur Vertex AIcomprendre la question, écrire le SQL, expliquerVertex AI, europe-west1
ADCidentifiants de votre compte, trouvés automatiquementgcloud auth application-default login

Pourquoi garder maximum_bytes_billed alors que le callback refuse déjà les requêtes trop chères au dry-run ?

Exercice : estimer avant de lancer

Avec la console BigQuery ou la commande bq, estimez sans rien payer le volume lu par ces deux requêtes, et expliquez la différence.

SELECT * FROM `bigquery-public-data.thelook_ecommerce.order_items` LIMIT 5;
SELECT status, COUNT(*) FROM `bigquery-public-data.thelook_ecommerce.order_items` GROUP BY status;
Voir la solution
terminal
bq query --project_id=VOTRE_PROJET --use_legacy_sql=false --dry_run \
  'SELECT * FROM `bigquery-public-data.thelook_ecommerce.order_items` LIMIT 5'

Le dry-run de la première annonce environ 13,6 Mo (toutes les colonnes, toute la table) ; la seconde, environ 1,9 Mo (une seule colonne, status). Le LIMIT 5 n'a rien changé. Notez qu'en facturation à la demande, BigQuery arrondit au Mo supérieur avec un minimum de 10 Mo par table lue : deux petites requêtes peuvent coûter autant.

Résultat obtenu

Dry-runs réels du 2026-10-15 lancés par la fonction estimer() du lab (rien n'est facturé) :

{'type': 'SELECT', 'octets': 1000032,   'tables': ['bigquery-public-data.thelook_ecommerce.orders']}
{'type': 'SELECT', 'octets': 384573827, 'tables': ['bigquery-public-data.thelook_ecommerce.events']}
{'type': 'SELECT', 'octets': 2610516,   'tables': ['bigquery-public-data.thelook_ecommerce.users']}

La première compte les commandes de 2025 (1 Mo lu : seule la colonne created_at) ; la deuxième lit toute la table events (385 Mo) ; la troisième lit les e-mails de users, une table que notre liste blanche refusera.

Je sais faire

  • Expliquer ce que BigQuery facture à la demande, et pourquoi LIMIT ne réduit pas la facture
  • Lancer un dry-run et lire les octets estimés
  • Distinguer le rôle du dry-run et celui de maximum_bytes_billed
  • Décrire l'architecture agent + toolset + callback de contrôle
Next