Storage et Lifecycle

Optimisez vos coûts de stockage BigQuery en comprenant les différents types de storage et les mécanismes d'expiration automatique.

Active vs Long-term Storage

TypePrixCondition
Active storage$0.02/GB/moisModifié dans les 90 derniers jours
Long-term storage$0.01/GB/moisNon modifié depuis 90+ jours

Succes

Bonne nouvelle : La bascule est automatique. Aucune action requise. Economie de 50% sur le storage après 90 jours d'inactivité.

A retenir

Ne faites rien pour le long-term storage, c'est automatique. Concentrez vos efforts sur la suppression des donnees inutiles et la reduction du Time Travel.

Time Travel

BigQuery conserve un historique des modifications pour permettre de requêter les données à un point dans le temps passé. Mais ça coûte du storage.

-- Requêter les données d'il y a 1 heure
SELECT * FROM `project.dataset.table`
FOR SYSTEM_TIME AS OF TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR);

-- Restaurer une table supprimée
CREATE TABLE `project.dataset.restored_table` AS
SELECT * FROM `project.dataset.deleted_table`
FOR SYSTEM_TIME AS OF TIMESTAMP('2025-01-15 10:00:00');

Réduire le coût du Time Travel

-- Par défaut : 7 jours (168 heures)
-- Réduire à 1 jour pour les tables non critiques
ALTER TABLE `project.dataset.staging_table`
SET OPTIONS (max_time_travel_hours = 24);

-- Minimum : 2 jours pour les tables avec streaming
ALTER TABLE `project.dataset.events`
SET OPTIONS (max_time_travel_hours = 48);

Erreur frequente

Garder 7 jours de Time Travel sur des tables de staging ou temporaires. Pour une table de 1 TB modifiee quotidiennement, 7 jours de Time Travel = 7 TB de storage facturable. Reduisez a 24h pour les tables non critiques.

Expiration automatique

Configurez l'expiration pour supprimer automatiquement les vieilles données.

-- Expiration des partitions (recommandé)
ALTER TABLE `project.dataset.events`
SET OPTIONS (partition_expiration_days = 365);
-- Les partitions de plus d'un an sont automatiquement supprimées

-- Expiration de table entière
ALTER TABLE `project.dataset.temp_table`
SET OPTIONS (expiration_timestamp = TIMESTAMP('2025-06-01'));

Identifier les tables inutilisées

-- Tables non modifiées depuis 90 jours
SELECT
  table_id,
  ROUND(size_bytes / POW(1024, 3), 2) as size_gb,
  ROUND(size_bytes / POW(1024, 3) * 0.02, 2) as monthly_cost_usd,
  TIMESTAMP_MILLIS(last_modified_time) as last_modified
FROM `project.dataset.__TABLES__`
WHERE TIMESTAMP_MILLIS(last_modified_time)
  < TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 90 DAY)
ORDER BY size_bytes DESC;
-- Tables jamais requêtées (via INFORMATION_SCHEMA)
SELECT
  t.table_name,
  t.total_rows,
  t.total_logical_bytes / POW(1024, 3) as size_gb
FROM `project.dataset.INFORMATION_SCHEMA.TABLES` t
LEFT JOIN (
  SELECT DISTINCT referenced_table.table_id
  FROM `region-us`.INFORMATION_SCHEMA.JOBS,
  UNNEST(referenced_tables) as referenced_table
  WHERE creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 90 DAY)
) j ON t.table_name = j.table_id
WHERE j.table_id IS NULL;

Decision concrete

Executez la requete ci-dessus chaque mois. Pour chaque table non utilisee depuis 90 jours, demandez au owner : archiver dans GCS (cout 10x moindre) ou supprimer ? Mettez une date limite de reponse.
Jonathan Kini

Jonathan Kini

J'aide les équipes data à réduire et maîtriser leurs coûts BigQuery et Snowflake, sans sacrifier la performance. 8 ans de terrain, de la startup aux environnements data à grande échelle.