Mettre en cache des DataFrames sur un compute serverless
Aperçu
Cette fonctionnalité est en Aperçu public. Les administrateurs du workspace peuvent contrôler l'accès au cache de DataFrame sur le compute serverless depuis la page Prévisualisations . Consultez Gérer les aperçus Databricks.
Sur le compute serverless, vous pouvez mettre en cache un DataFrame avec df.cache() ou df.persist() afin de réutiliser un résultat coûteux au cours de votre session. Databricks compute le DataFrame lorsque vous appelez cache() et matérialise le résultat sous forme de instantané. Le DataFrame et les DataFrames que vous en tirez lisent alors l’instantané pour le reste de votre session au lieu de le recalculer.
Configuration requise
- L’aperçu de la mise en cache DataFrame sur le compute Serverless est activé pour votre Workspace (activé par default). Les administrateurs du workspace peuvent le désactiver à partir de la page Prévisualisations . L’aperçu n’est pas disponible dans les Workspace avec le profil de sécurité de la conformité activé. Consultez Gérer les aperçus au niveau de Workspace.
- Les notebooks et les jobs sur le compute serverless doivent utiliser la version d'environnement 5 ou ultérieure.
- Databricks Connect pour Python doit être 18.1.8 ou version ultérieure, et Databricks Connect pour Scala doit être 18.1.5 ou version ultérieure.
Les anciens clients reçoivent l'erreur CACHE_REQUIRES_NEWER_CLIENT_ON_SERVERLESS_GC.
Quand utiliser la mise en cache DataFrame sur le compute serverless
Mettez en cache un DataFrame sur le compute serverless lorsque vous devez :
- Réutilisez le résultat d’une jointure, d’une agrégation ou d’un filtre coûteux plusieurs fois au cours de la même session.
- Computez un micro-batch de streaming une fois dans une fonction
foreachBatch, puis écrivez-le dans plusieurs puits de données. - Entraînez ou ajustez plusieurs modèles de machine learning sur les mêmes données de fonctionnalité préparées.
- Conservez un instantané stable pendant que vous exécutez plusieurs étapes d'une analyse, même si les tables source changent.
Voir les Bonnes pratiques.
APIs DataFrame de cache sur le compute Serverless
L'exemple suivant met en cache une journée de commandes jointes aux données client, compute le chiffre d'affaires total de la journée, ajoute le chiffre d'affaires par région à une table de rapport, puis libère le cache. Les deux résultats lisent l'instantané mis en cache au lieu d'exécuter à nouveau la jointure.
- Python
- Scala
from pyspark.sql import functions as F
# The DataFrame to cache: one day of orders joined with customer data.
oct_15_orders = (
spark.table("main.sales.orders")
.filter(F.col("order_date") == "2026-10-15")
.join(spark.table("main.sales.customers"), "customer_id")
)
oct_15_orders.cache()
# Both results are built from oct_15_orders, so they read the cached snapshot.
total_revenue = oct_15_orders.agg(F.sum("amount")).first()[0]
print(f"Total revenue on 2026-10-15: {total_revenue}")
revenue_by_region = oct_15_orders.groupBy("order_date", "region").agg(F.sum("amount").alias("revenue"))
revenue_by_region.write.mode("append").saveAsTable("main.reports.revenue_by_region")
# Release the cache and the DataFrame when you no longer need it.
# oct_15_orders and DataFrames built from it can no longer be used.
oct_15_orders.unpersist()
import org.apache.spark.sql.functions._
// The DataFrame to cache: one day of orders joined with customer data.
val oct15Orders = spark.table("main.sales.orders")
.filter(col("order_date") === "2026-10-15")
.join(spark.table("main.sales.customers"), "customer_id")
oct15Orders.cache()
// Both results are built from oct15Orders, so they read the cached snapshot.
val totalRevenue = oct15Orders.agg(sum("amount")).first().get(0)
println(s"Total revenue on 2026-10-15: $totalRevenue")
val revenueByRegion = oct15Orders.groupBy("order_date", "region").agg(sum("amount").alias("revenue"))
revenueByRegion.write.mode("append").saveAsTable("main.reports.revenue_by_region")
// Release the cache and the DataFrame when you no longer need it.
// oct15Orders and DataFrames built from it can no longer be used.
oct15Orders.unpersist()
Dans les descriptions d'API suivantes, df représente n'importe quel DataFrame dans votre session, comme oct_15_orders dans l'exemple précédent.
df.cache()
Le compute df immédiatement et met en cache le résultat sous forme d' instantané pour le reste de votre session.
- Renvoie : le même DataFrame mis en cache,
df, désormais basé sur le snapshot plutôt que sur le calcul effectué sur ses tables sources. Voir le comportement suivant. - Comportement :
- Exécute immédiatement la query du DataFrame et matérialise le résultat sous forme de capture instantanée avant le retour de l’appel.
- Après l’appel,
dfet le DataFrame renvoyé (dflui-même) sont basés sur l’instantané. Ils ne sont plus connectés au calcul effectué sur les tables sources ; ils lisent donc l’instantané au lieu de recalculer la query. - Les DataFrames dérivés de
df, directement ou par le biais d’autres DataFrames dérivés, lisent automatiquement l’instantané au lieu d’exécuter à nouveau la query d’origine. Voir Lire l'instantané. - L’instantané est local à votre session. Seule la session ayant mis en cache
dfpeut la lire. Consultez Isolation et privilèges. - L’instantané est conservé jusqu’à la fin de la session, pour une durée maximale de sept jours. Databricks récupère ensuite automatiquement son stockage en arrière-plan. Appeler
df.unpersist()lui permet de récupérer le stockage plus tôt. Voir Cycle de vie et délais et Stockage et nettoyage. - Si le calcul de
dféchoue,df.cache()soulève l'erreur etdfn'est pas mis en cache. - Appeler
df.cache()sur un DataFrame déjà mis en cache ne fait rien.dfn'est pas compute à nouveau.
L’instantané est figé après avoir appelé df.cache(). Les données écrites par la suite dans les tables à partir desquelles df effectue ses lectures, ainsi que les modifications de schéma apportées à ces tables (ajout ou renommage de colonnes, par exemple), n’ont aucun impact. Pour effectuer un nouveau calcul à partir des dernières données, reconstruisez le DataFrame à partir des tables sources et mettez le nouveau DataFrame en cache si nécessaire.
Lire l’aperçu instantané
Sur le compute Serverless, la correspondance du cache est basée sur la dérivation du DataFrame. Après df.cache(), seuls les DataFrames suivants lisent automatiquement l'instantané au lieu de recalculer la query sur les tables sources :
- Le DataFrame que vous avez mis en cache,
df. - DataFrames dérivés de
df, par exemple avecselect(),filter(),groupBy()oujoin(). - DataFrames enchaînés à partir de ces DataFrames dérivés.
Un nouveau DataFrame qui répète la même query lit les tables sources, même si sa logique est identique, car il n’est pas dérivé de df.
Cela rend la correspondance du cache explicite et sous votre contrôle : un DataFrame ne lit les données mises en cache que lorsque vous les dérivez d’un DataFrame mis en cache. Tous les autres DataFrame lisent les tables sources.
- Python
- Scala
oct_15_orders = (
spark.table("main.sales.orders")
.filter(F.col("order_date") == "2026-10-15")
.join(spark.table("main.sales.customers"), "customer_id")
)
# The join runs one time, when you call cache().
oct_15_orders.cache()
# Derived from oct_15_orders: read the snapshot, so the join doesn't run again.
large_orders = oct_15_orders.filter(F.col("amount") > 1000)
revenue_by_region = oct_15_orders.groupBy("order_date", "region").agg(F.sum("amount").alias("revenue"))
# Derived from large_orders, which is derived from oct_15_orders: also reads the snapshot.
large_orders_by_region = large_orders.groupBy("region").count()
# Not derived from oct_15_orders: reads the source tables and runs the join again.
same_query = (
spark.table("main.sales.orders")
.filter(F.col("order_date") == "2026-10-15")
.join(spark.table("main.sales.customers"), "customer_id")
)
val oct15Orders = spark.table("main.sales.orders")
.filter(col("order_date") === "2026-10-15")
.join(spark.table("main.sales.customers"), "customer_id")
// The join runs one time, when you call cache().
oct15Orders.cache()
// Derived from oct15Orders: read the snapshot, so the join doesn't run again.
val largeOrders = oct15Orders.filter(col("amount") > 1000)
val revenueByRegion = oct15Orders.groupBy("order_date", "region").agg(sum("amount").alias("revenue"))
// Derived from largeOrders, which is derived from oct15Orders: also reads the snapshot.
val largeOrdersByRegion = largeOrders.groupBy("region").count()
// Not derived from oct15Orders: reads the source tables and runs the join again.
val sameQuery = spark.table("main.sales.orders")
.filter(col("order_date") === "2026-10-15")
.join(spark.table("main.sales.customers"), "customer_id")
Comme df lit l’instantané plutôt que les DataFrames à partir desquels il a été créé, vous ne pouvez pas référencer les colonnes de df par le biais de ces DataFrames. Voir Limitations.
df.persist(storageLevel)
Alias de df.cache() qui accepte un niveau de stockage.
- Paramètres :
storageLevel(facultatif) : unStorageLevel, par exempleStorageLevel.DISK_ONLY. le serverless compute accepte tout niveau de stockage et l'ignore. La capture est stockée de la même manière pour chaque niveau de stockage, etdf.storageLevelretourneStorageLevel.DISK_ONLY.
La valeur renvoyée et le comportement sont les mêmes que pour df.cache().
df.unpersist(blocking)
Libère l'instantané mis en cache de df et détruit le DataFrame.
-
Paramètres :
blocking(optionnel) : Ignoré.df.unpersist()renvoie immédiatement pour chaque valeur.
-
Retourne : le même DataFrame,
df, désormais détruit. -
Comportement :
- Marque l’instantané comme prêt à être récupéré. Databricks supprime ensuite les données mises en cache et récupère l'espace de stockage en arrière-plan.
- Détruit
df:dfet tous les DataFrames précédemment dérivés de celui-ci ne sont plus utilisables, et toute query ultérieure sur ceux-ci génèreCACHE_DATAFRAME_ACCESS_AFTER_UNCACHE. Si vous mettez en cache un DataFrame dérivé dedfavant d'appelerdf.unpersist(), ce DataFrame reste utilisable car il possède son propre instantané. - Pour continuer à utiliser la même source de données, créez un nouveau DataFrame à partir de la source de données d’origine, au lieu de réutiliser le DataFrame non mis en cache.
- Appeler
df.unpersist()sur un DataFrame qui n'a jamais été mis en cache ou qui a déjà été supprimé du cache est une opération sans effet.
Appelez df.unpersist() lorsque vous n'avez plus besoin des données en cache, par exemple lorsqu'aucune étape ultérieure de votre notebook ou job ne les lit. Cela permet à Databricks de récupérer le stockage plus tôt. N’utilisez pas df.unpersist() pour refresh les données. Pour travailler avec les dernières données, créez un nouveau DataFrame à partir des tables sources.
- Python
- Scala
oct_15_orders = spark.table("main.sales.orders").filter(F.col("order_date") == "2026-10-15")
oct_15_orders.cache()
large_orders = oct_15_orders.filter(F.col("amount") > 1000)
orders_per_customer = oct_15_orders.groupBy("customer_id").count()
orders_per_customer.cache() # Has its own snapshot.
# Acknowledge that the cached data is no longer needed.
# This releases the storage and destroys oct_15_orders.
oct_15_orders.unpersist()
oct_15_orders.count() # Raises CACHE_DATAFRAME_ACCESS_AFTER_UNCACHE.
large_orders.count() # Raises CACHE_DATAFRAME_ACCESS_AFTER_UNCACHE.
orders_per_customer.count() # Reads its own snapshot.
# If you need the data again later, build a new DataFrame from the source tables.
oct_15_orders = spark.table("main.sales.orders").filter(F.col("order_date") == "2026-10-15")
var oct15Orders = spark.table("main.sales.orders").filter(col("order_date") === "2026-10-15")
oct15Orders.cache()
val largeOrders = oct15Orders.filter(col("amount") > 1000)
val ordersPerCustomer = oct15Orders.groupBy("customer_id").count()
ordersPerCustomer.cache() // Has its own snapshot.
// Acknowledge that the cached data is no longer needed.
// This releases the storage and destroys oct15Orders.
oct15Orders.unpersist()
oct15Orders.count() // Throws CACHE_DATAFRAME_ACCESS_AFTER_UNCACHE.
largeOrders.count() // Throws CACHE_DATAFRAME_ACCESS_AFTER_UNCACHE.
ordersPerCustomer.count() // Reads its own snapshot.
// If you need the data again later, build a new DataFrame from the source tables.
oct15Orders = spark.table("main.sales.orders").filter(col("order_date") === "2026-10-15")
df.storageLevel
Obtient le niveau de stockage de df.
- Renvoie :
StorageLevel.DISK_ONLYalors quedfest mis en cache.StorageLevel.NONEavant de le mettre en cache et après avoir appelédf.unpersist().
- Python
- Scala
from pyspark import StorageLevel
oct_15_orders.cache()
oct_15_orders.storageLevel == StorageLevel.DISK_ONLY # True
import org.apache.spark.storage.StorageLevel
oct15Orders.cache()
oct15Orders.storageLevel == StorageLevel.DISK_ONLY // true
Pour les signatures de méthode, voir la référence PySpark pour cache, persist, unpersist et storageLevel.
Limites de cycle de vie et de temps
Les données mises en cache n’existent que dans la session Databricks où vous les mettez en cache. Elle devient inaccessible à la fin de la session et dure au maximum sept jours. Après la limite de sept jours, l’utilisation d’un DataFrame mis en cache déclenche une erreur au lieu de lire à nouveau les tables sources. Pour mettre à nouveau en cache, start une nouvelle session.
Stockage et nettoyage
Databricks gère automatiquement le stockage des données mises en cache. Les données mises en cache sont stockées dans le stockage cloud, l’emplacement de stockage précis dépendant du type de votre workspace :
-
Workspace Serverless : Les données en cache sont stockées dans le stockage par default. Si vous avez configuré une clé gérée par le client pour les services gérés, les données en cache utilisent cette clé. Voir Clés gérées par le client pour le chiffrement.
-
Workspace classiques : les données mises en cache sont stockées dans le bucket de stockage du Workspace qui est configuré lors de la création du Workspace. Vous pouvez configurer le chiffrement au niveau du compartiment de stockage.
Une fois que les données en cache deviennent inaccessibles, Databricks récupère automatiquement le stockage en arrière-plan. Cela inclut les cas où la session prend fin à cause d’une déconnexion ou d’un plantage. L'appel de df.unpersist() permet à Databricks de récupérer le stockage plus rapidement.
Isolement et privilèges
Tout utilisateur pouvant exécuter du code sur un compute serverless peut mettre en cache un DataFrame. Vous n'avez besoin d'aucun privilège supplémentaire.
Les données mises en cache offrent une isolation au niveau de la session. Seule la session qui a mis en cache un DataFrame peut lire ses données mises en cache. Les autres utilisateurs ne peuvent pas y accéder, y compris les autres utilisateurs du même notebook.
Les données mises en cache contiennent ce que vous étiez autorisé à lire lorsque vous les avez mises en cache. Les modifications de permissions, les filtres de ligne et les masques de colonne appliqués aux tables sources ultérieurement ne s’appliquent pas aux données mises en cache.
Bonnes pratiques
- Cache lorsque vous avez besoin d’un instantané stable : si vous exécutez plusieurs transformations, agrégations ou explorations sur les mêmes données calculées, l’instantané leur fournit une ligne de base cohérente qui ne change pas lorsque les tables sources changent.
- Mettez en cache les calculs coûteux, pas les lectures de tables simples :
df.cache()matérialise le résultat de la query, et les lectures ultérieures scannent cet instantané. Si vous mettez en cache une lecture de table simple, commespark.table("main.sales.orders").cache(), les lectures ultérieures scannent toujours une copie complète de la table, donc la mise en cache n'apporte que peu d'économies. La mise en cache est avantageuse après des opérations coûteuses telles que des jointures, des agrégations et des filtres complexes. - Ne mettez pas en cache les données que vous ne lisez qu'une seule fois :
df.cache()compute et stocke le résultat immédiatement, ce qui prend du temps et de l'espace de stockage. Si vous ne lisez le résultat qu'une seule fois, le coût initial n'en vaut pas la peine. - Utilisez le cache en dérivant du DataFrame mis en cache : pour lire l'instantané, construisez les opérations ultérieures à partir de la variable DataFrame mise en cache, par exemple
df.select(...)oudf.filter(...). Un DataFrame indépendant construit à partir du même calcul sur les tables source n'utilise pas le cache. - N’utilisez pas le cache pour le Data Sharing entre sessions ou entre utilisateurs : les données mises en cache sont privées pour votre session. Les autres sessions, Notebook, exécutions de Job et utilisateurs ne peuvent pas les lire. Pour partager les résultats calculés entre les sessions ou avec d’autres utilisateurs, écrivez-les dans une table permanente.
- Conservez les sessions avec les données mises en cache pendant moins de sept jours : consultez Cycle de vie et limites de temps. Si votre workflow a besoin des données pendant plus longtemps, écrivez-les dans une table.
- Appelez
df.unpersist()lorsque vous n’avez plus besoin des données en cache : Cela permet à Databricks de récupérer le stockage plus tôt. Après l’appel, le DataFrame et les DataFrames qui en sont dérivés ne peuvent pas être utilisés. - N’utilisez pas
df.unpersist()pour refresh les données :df.unpersist()met fin à la durée de vie de l’instantané. Pour récupérer les modifications dans les tables sources, créez un nouveau DataFrame à partir des tables sources.
Limites
La mise en cache de DataFrame sur le compute serverless a les limitations suivantes :
-
Noms et types de colonnes : Les DataFrames suivants ne peuvent pas être mis en cache. Renommez ou convertissez les colonnes avant de mettre en cache, par exemple avec
.alias("total_amount").- DataFrames avec des noms de colonne en double.
- DataFrames avec des noms de colonne qui contiennent des espaces ou l'un des caractères
,;{}()=, commesum(amount)à partir d'une agrégation. - DataFrames avec des colonnes d'intervalle.
- DataFrames contenant des tableaux, des maps ou des structs qui contiennent des valeurs de type NULL.
- DataFrames sans colonnes, ou avec uniquement des colonnes de type NULL.
-
Références de colonne : après avoir mis en cache un DataFrame, vous ne pouvez pas référencer ses colonnes via les DataFrames à partir desquels il a été construit. Par exemple, après
oct_15_orders = orders.join(customers, "customer_id")etoct_15_orders.cache(),oct_15_orders.select(orders.amount)déclencheCANNOT_RESOLVE_DATAFRAME_COLUMN. Utilisez plutôtoct_15_orders.amountou"amount". -
SQL and catalog cache APIs : les instructions de cache SQL, telles que
CACHE TABLE, et les méthodes de cache de table despark.catalogne sont pas prises en charge sur le Serverless compute. Voir Limites du cache. Pour réutiliser un résultat de query en SQL, utilisez une table temporaire locale à la session. -
Requêtes de schéma d'information : lorsque de nombreuses sessions dans un metastore mettent en cache des DataFrames, les requêtes sur
information_schema.volumesetinformation_schema.schematapeuvent être lentes ou expirer. Le filtrage devolumespar catalogue ne rend pas la query plus rapide. Les requêtes surinformation_schema.tablesne sont pas affectées. -
Paramètres ignorés :
df.persist(storageLevel)ignore le niveau de stockage, etdf.unpersist(blocking)ignoreblocking. Voirdf.persist(storageLevel)etdf.unpersist(blocking).
Migrer depuis Classic Compute
Pour la plupart des charges de travail, la mise en cache sur le compute Serverless donne les mêmes résultats que sur le compute classique, et le code existant s'exécute sans modification. Le tableau suivant détaille les différences.
Comportement | Compute serverless | Classic Compute |
|---|---|---|
Correspondance du cache | Seuls le DataFrame mis en cache et les DataFrames dérivés de celui-ci utilisent automatiquement le cache. | Toute query avec la même forme de plan utilise automatiquement le cache. |
Récence des données | Un instantané cohérent pris au moment où vous appelez | Varie : les données mises en cache sont actualisées dans certains cas et fournissent un instantané dans d’autres. |
Périmètre de partage | Privé pour votre session. | Partagé entre les sessions du cluster. |
Matérialisation | Eager : calculé immédiatement lorsque vous appelez | Lazy : calculé lors de la première action sur le DataFrame. |
| Détruit le DataFrame et libère son instantané de manière déterministe. | Libère le cache en mémoire. L'utilisation ultérieure du DataFrame peut obtenir les données les plus récentes ou obsolètes, en fonction du produit et de la source de données. |
Ce qui suit décrit plus en détail les deux premières différences :
-
Correspondance du cache :
- Workloads affectés par le changement : la plupart des workloads ne sont pas affectés. Si vous continuez à utiliser la variable DataFrame mise en cache, par exemple avec
df.select(...)oudf.filter(...), le cache fonctionne comme avant. La modification n’affecte que les charges de travail où un DataFrame ou une query SQL créée indépendamment réutilise le cache car il présente la même forme de plan. Sur le compute Serverless, ces query lisent les tables sources. - Si votre charge de travail est affectée : utilisez la variable DataFrame mise en cache partout où vous avez besoin du résultat mis en cache, au lieu de reconstruire la même query.
- Workloads affectés par le changement : la plupart des workloads ne sont pas affectés. Si vous continuez à utiliser la variable DataFrame mise en cache, par exemple avec
-
Récence des données :
- Charges de travail affectées par le changement : La plupart des charges de travail ne sont pas affectées, car il est rare de lire à nouveau les données mises en cache après avoir écrit dans leurs tables sources. Le changement affecte uniquement les charges de travail qui écrivent dans les tables sources puis attendent que le DataFrame mis en cache affiche les nouvelles données.
- Si votre workload est impacté : Après avoir écrit sur les tables source, construisez un nouveau DataFrame à partir de celles-ci au lieu de réutiliser celui qui a été mis en cache.