Ukládat DataFrames do mezipaměti ve výpočetním prostředí bez serverů

Important

Tato funkce je ve verzi Public Preview. Správci pracovního prostoru mohou spravovat přístup k ukládání DataFrame do mezipaměti ve výpočetním prostředí serverless na stránce Previews. Viz Manage Azure Databricks preview.

V serverless výpočetním režimu můžete uložit DataFrame do mezipaměti pomocí df.cache() nebo df.persist(), abyste ve své relaci mohli znovu použít nákladný výsledek. Azure Databricks při volání cache() vypočítá DataFrame a výsledek materializuje jako snapshot. DataFrame a DataFramy, které z něj postavíte, pak čtou snapshot po zbytek relace místo toho, abyste ho znovu počítali.

Requirements

  • Náhled ukládání DataFrame do mezipaměti ve výpočetním prostředí serverless je pro váš pracovní prostor povolen (ve výchozím nastavení). Správci pracovního prostoru to mohou vypnout na stránce Náhledy . Náhled není dostupný v pracovních prostorech s aktivovaným bezpečnostním profilem compliance . Podívejte se na Správu Preview na úrovni pracovního prostoru.
  • Notebooky a úlohy v serverless výpočetním prostředí musí používat verzi prostředí 5 nebo vyšší.
  • Databricks Connect pro Python musí být 18.1.8 nebo novší, a Databricks Connect pro Scalu musí být 18.1.5 nebo vyšší.

Starší klienti dostávají chybu CACHE_REQUIRES_NEWER_CLIENT_ON_SERVERLESS_GC.

Kdy používat caching DataFrame ve výpočetním prostředí bez serverů

Uložte DataFrame do mezipaměti na serverless výpočetních prostředcích, když potřebujete:

  • Výsledek nákladného spojení, agregace nebo filtru lze během jedné relace několikrát znovu použít.
  • Jednou vypočítejte streamovací mikro-batch ve foreachBatch funkci a poté jej zapište do několika výstupů.
  • Trénujte nebo laděte několik modelů strojového učení na stejných připravených datech příznaků.
  • Udržujte stabilní snapshot, zatímco provádíte několik kroků analýzy, i když se zdrojové tabulky mění.

Viz Osvědčené postupy.

Ukládání rozhraní API DataFrame do mezipaměti v bezserverovém výpočetním prostředí

Následující příklad ukládá jeden den objednávek spojených s daty zákazníků, vypočítá celkové příjmy za daný den, připojí příjmy podle regionů do tabulky zpráv a poté cache uvolní. Oba výsledky čítají cachovaný snapshot místo opětovného spuštění joinu.

Python

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()

Scala

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()

V následujících popisech API znamená df jakýkoli DataFrame ve vaší relaci, například oct_15_orders v předchozím příkladu.

df.cache()

Okamžitě to df spočítá a výsledek si uloží jako snímek pro zbytek vaší relace.

  • Vrací: Stejný cachovaný DataFrame, df, nyní založený na snapshotu místo výpočtu nad svými zdrojovými tabulkami. Podívejte se na následující chování.
  • Chování:
    • Ihned spustí dotaz DataFrame a výsledek materializuje jako snapshot ještě před návratem volání.
    • Po volání jsou df i vrácený DataFrame (df sám o sobě) založeny na snímku. Už nejsou navázány na výpočet nad zdrojovými tabulkami, takže čtou snapshot místo toho, aby znovu počítaly dotaz.
    • DataFrames odvozené z df, přímo nebo prostřednictvím jiných odvozených DataFrames, automaticky načtou snímek místo opětovného spuštění původního dotazu. Viz Přečtěte si snapshot.
    • Snímek je lokální pro vaši relaci. Pouze relace, která ji uložila do mezipaměti df, ji může číst. Viz Izolace a privilegia.
    • Snímek trvá až do konce relace, maximálně sedm dní. Azure Databricks pak automaticky uvolní svůj úložný prostor na pozadí. Volání df.unpersist() mu umožňuje uvolnit místo v úložišti dříve. Viz Životní cyklus a časové limity a Úložiště a úklid.
    • Pokud výpočet df selže, df.cache() vyvolá chybu a df není uložena do cache.
    • Volání df.cache() na DataFrame, který je už uložený v cache, nic nedělá. df se znovu nepočítá.

Snapshot je zafixován po zavolání df.cache(). Data zapisovaná později do tabulek, ze kterých df čte, a změny schématu těchto tabulek, jako jsou přidané nebo přejmenované sloupce, ji neovlivňují. Pro přepočítání z nejnovějších dat znovu sestavte DataFrame ze zdrojových tabulek a pokud je potřeba, uložte nový DataFrame do mezipaměti.

Přečti si snímek systému

V bezserverovém výpočetním režimu je porovnávání cache založeno na odvození DataFrame. Po df.cache() pouze následující datové rámce automaticky načtou snímek místo opětovného výpočtu dotazu nad zdrojovými tabulkami:

  • DataFrame, který jste uložili do cache, df.
  • DataFrames odvozené z df, například s select(), filter(), groupBy() nebo join().
  • DataFrames byly dále zřetězeny z těchto odvozených DataFrames.

Nový DataFrame, který opakuje stejný dotaz, čte zdrojové tabulky, i když jeho logika je identická, protože není odvozen z df.

To umožňuje explicitní a pod vaší kontrolou porovnávání cache: DataFrame čte cache data pouze tehdy, když jej odvodíte z cacheovaného DataFrame. Každý druhý DataFrame čte zdrojové tabulky.

Python

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")
)

Scala

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")

Protože df čte snapshot místo DataFrames, ze kterých byl postaven, nemůžete odkazovat na sloupce df prostřednictvím těchto DataFrames. Viz Omezení.

df.persist(storageLevel)

Alias prvku df.cache(), který přijímá úroveň úložiště.

  • Parametry:
    • storageLevel (volitelné): Například StorageLevel, jako je StorageLevel.DISK_ONLY. Serverless compute přijímá jakoukoli úroveň úložiště a ignoruje ji. Snapshot je uložen stejným způsobem pro každou úroveň úložiště a df.storageLevel vrací StorageLevel.DISK_ONLY.

Návratová hodnota a chování jsou stejné jako u df.cache().

df.unpersist(blocking)

Uvolní cacheovaný snímek df a zničí DataFrame.

  • Parametry:
    • blocking (volitelné): Ignorováno. df.unpersist() Okamžitě vrátí obě hodnoty.
  • Návratová hodnota: Stejný DataFrame, df, nyní zničený.
  • Chování:
    • Označí snímek jako připravený k uvolnění. Azure Databricks pak smaže uložená data a na pozadí uvolní úložný prostor.
    • Zničí df: df a všechny DataFrames, které z něj dříve byly odvozeny, již nejsou použitelné, a jakýkoli následný dotaz na ně vyvolá CACHE_DATAFRAME_ACCESS_AFTER_UNCACHE. Pokud uložíte do cache DataFrame odvozený z df tím, než zavoláte df.unpersist(), ten DataFrame zůstává použitelný, protože má svůj vlastní snapshot.
    • Pro pokračování práce se stejným datovým zdrojem vytvořte nový DataFrame z původního zdroje, místo opětovného použití necacheovaného DataFrame.
    • Volání df.unpersist() na objektu DataFrame, který nikdy nebyl uložen do cache nebo který už byl odcacheován, je no-op.

Zavolejte funkci df.unpersist(), když už nepotřebujete uložená data, například když je nepřečte žádný další krok v notebooku nebo úloze. To umožňuje Azure Databricks uvolnit úložiště dříve. Nepoužívejte df.unpersist() k obnovení dat. Pro práci s nejnovějšími daty vytvořte nový DataFrame ze zdrojových tabulek.

Python

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")

Scala

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

Získá úroveň úložiště df.

  • Vrácení: StorageLevel.DISK_ONLY zatímco df je v cache. StorageLevel.NONE před uložením do mezipaměti a po zavolání df.unpersist().

Python

from pyspark import StorageLevel

oct_15_orders.cache()
oct_15_orders.storageLevel == StorageLevel.DISK_ONLY  # True

Scala

import org.apache.spark.storage.StorageLevel

oct15Orders.cache()
oct15Orders.storageLevel == StorageLevel.DISK_ONLY // true

Pro podpisy metod viz odkaz PySpark pro cache, persist, unpersist a storageLevel.

Životní cyklus a časové limity

Cacheovaná data existují pouze v rámci relace Azure Databricks, kde je ukládáte do cache. Po skončení sezení se stává nepřístupným a trvá maximálně sedm dní. Po uplynutí sedmidenního limitu způsobí použití cacheovaného DataFrame chybu místo opětovného čtení zdrojových tabulek. Pro opětovné ukládání do mezipaměti začněte novou relaci.

Úložiště a vyčištění

Azure Databricks automaticky spravuje úložiště cacheovaných dat. Data v mezipaměti jsou uložena v cloudovém úložišti, přičemž konkrétní umístění úložiště závisí na typu vašeho pracovního prostoru:

  • Serverless pracovní prostory: Data mezipaměti jsou uložena ve výchozím úložišti. Pokud máte nastavený klíč spravovaný zákazníkem pro spravované služby, cachovaná data používají tento klíč. Informace o šifrování najdete v tématu Klíče spravované zákazníkem.
  • Klasické pracovní prostory: Data uložená v mezipaměti jsou uložena v účtu úložiště pracovního prostoru, který je nastaven při vytváření pracovního prostoru. Šifrování můžete nastavit na úrovni úložného účtu.

Poté, co se data v mezipaměti stanou nedostupnými, Azure Databricks automaticky na pozadí uvolní kapacitu úložiště. To zahrnuje případy, kdy relace končí kvůli odpojení nebo pádu. Volání df.unpersist() umožňuje službě Azure Databricks uvolnit úložiště dříve.

Izolace a oprávnění

Každý uživatel, který může spouštět kód na serverless výpočetním systému, může DataFrame ukládat do cache. Nepotřebujete žádná další oprávnění.

Cacheovaná data poskytují izolaci na úrovni relace. Pouze session, která uložila DataFrame do mezipaměti, může číst jeho uložená data. Ostatní uživatelé k němu nemají přístup, včetně dalších uživatelů stejného poznámkového bloku.

Uložená data obsahují to, co jste směli číst, když jste je ukládali. Změny oprávnění, řádkové filtry a sloupcové masky aplikované na zdrojové tabulky se na cacheovaná data nevztahují.

Doporučené postupy

  • Cache, když potřebujete stabilní snapshot: Pokud provedete několik transformací, agregací nebo drill-downů na stejných vypočítaných datech, snapshot jim poskytne konzistentní základnu, která se nemění, když se změní zdrojové tabulky.
  • Ukládejte do mezipaměti nákladné výpočty, nikoli obyčejné čtení tabulek: df.cache() materializuje výsledek dotazu a pozdější čtení prohledávají tento snímek. Pokud uložíte do cache obyčejné čtení tabulky, například spark.table("main.sales.orders").cache(), pozdější čtení stále procházejí celou kopii tabulky, takže cachování ušetří jen málo. Cachování se vyplácí po nákladné práci, jako jsou joiny, agregace a složité filtry.
  • Nekešujte data, která čtete jen jednou: df.cache() okamžitě vypočítá a uloží výsledek, což zabere čas a úložiště. Pokud si výsledek přečtete jen jednou, počáteční náklady za to nestojí.
  • Použijte mezipaměť tak, že budete vycházet z DataFrame uloženého v mezipaměti: Pro čtení snapshotu vytvářejte následné operace z proměnné DataFrame uložené v mezipaměti, například df.select(...) nebo df.filter(...). Nezávislý DataFrame postavený ze stejného výpočtu na zdrojových tabulkách cache nepoužívá.
  • Nepoužívejte cache pro sdílení dat mezi relacemi nebo uživateli: Cache data jsou soukromá pro vaši relaci. Jiné relace, notebooky, běhy úloh a uživatelé je nemohou číst. Pro sdílení vypočtených výsledků napříč relacemi nebo s ostatními uživateli je zapisujte do trvalé tabulky.
  • Udržujte relace s uloženými daty kratší než sedm dní: viz Životní cyklus a časové limity. Pokud váš pracovní postup potřebuje data déle, zapisujte je do tabulky.
  • Volejte df.unpersist(), když už nebudete potřebovat data uložená v mezipaměti: To umožňuje Azure Databricks dříve uvolnit úložný prostor. Po volání nelze DataFrame ani DataFrames z něj odvozené použít.
  • Nepoužívat df.unpersist() k obnově dat: df.unpersist() ukončí životnost snímku. Pro zachytení změn ve zdrojových tabulkách vytvořte nový DataFrame ze zdrojových tabulek.

Omezení

Cachování DataFrame v bezserverovém výpočetním prostředí má následující omezení:

  • Názvy a typy sloupců: Následující DataFrames nelze ukládat do cache. Přejmenujte nebo přetypujte sloupce před uložením do cache, například pomocí .alias("total_amount").
    • DataFrames s duplicitními názvy sloupců.
    • DataFrames s názvy sloupců, které obsahují mezery nebo libovolný z těchto znaků ,;{}()=, například sum(amount) z agregace.
    • DataFrames s intervalovými sloupci.
    • DataFrames s poli, mapami nebo strukturami obsahujícími hodnoty typu NULL.
    • DataFrames bez sloupců nebo pouze s NULL-typovanými sloupci.
  • Odkazy na sloupce: Po cacheování DataFrame už nemůžete odkazovat na jeho sloupce přes DataFrame, ze kterých byl vytvořen. Například po oct_15_orders = orders.join(customers, "customer_id") a oct_15_orders.cache(), oct_15_orders.select(orders.amount) zvyšuje CANNOT_RESOLVE_DATAFRAME_COLUMN. Použijte oct_15_orders.amount nebo "amount" místo toho.
  • SQL a katalogová cache API: SQL cache příkazy, jako CACHE TABLE, a metody tabulkové cache objektu spark.catalog nejsou v prostředí serverless computingu podporovány. Viz také omezení mezipaměti. Pro opětovné použití výsledku dotazu v SQL použijte dočasnou tabulku místní pro relaci.
  • Dotazy na informační schémata: Když mnoho relací v metastore cachuje DataFrames, dotazy na information_schema.volumes a information_schema.schemata mohou být pomalé nebo u nich může vypršet časový limit. Filtrování volumes podle katalogu dotaz nezrychluje. Dotazy na information_schema.tables nejsou ovlivněny.
  • Azure Government regiony: DataFrame caching není podporováno v bezserverových výpočetních prostředcích v Azure Government regionech.

Migrujte z klasických výpočtů

U většiny pracovních zátěží poskytuje cache na serverless compute stejné výsledky jako u klasického výpočetního prostředí a existující kód běží bez změn. Následující tabulka uvádí rozdíly.

Behavior Výpočetní prostředí bez serveru Klasické výpočetní prostředky
Shoda mezipaměti Pouze DataFrame uložený v mezipaměti a DataFrames odvozené z něj automaticky používají mezipaměť. Každý dotaz se stejným tvarem plánu automaticky používá cache.
Aktuálnost dat Konzistentní snímek pořízený v okamžiku volání df.cache(). Liší se: cachovaná data se v určitých případech obnovují a v jiných slouží jako snapshot.
Rozsah sdílení Soukromé pro vaši relaci. Sdíleno mezi relacemi v rámci clusteru.
Zhmotnění Eager: počítá se ihned při volání df.cache(). Lazy: vypočítáno při první akci na DataFrame.
df.unpersist() DataFrame zničí a deterministicky uvolní jeho snímek. Uvolní cache v paměti. Pozdější použití DataFrame může vrátit nejnovější nebo zastaralá data v závislosti na produktu a zdroji dat.

Následující text podrobněji popisuje první dva rozdíly:

  • Shoda mezipaměti:
    • Úlohy ovlivněné změnou: Většina úloh není ovlivněna. Pokud budete dál používat cacheovanou proměnnou DataFrame, například s df.select(...) nebo df.filter(...), cache funguje jako dříve. Změna se týká pouze pracovních zátěží, kde nezávisle vytvořený DataFrame nebo SQL dotaz znovu používá cache, protože má stejnou strukturu plánu. V serverless výpočetním režimu tyto dotazy čtou zdrojové tabulky.
    • Pokud je ovlivněno vaše zatížení: Používejte cacheovanou proměnnou DataFrame tam, kde potřebujete cacheovaný výsledek, místo abyste vytvářeli stejný dotaz znovu.
  • Čerstvost dat:
    • Pracovní zátěže ovlivněné změnou: Většina zátěží není ovlivněna, protože opětovné čtení cacheovaných dat po zápisu do zdrojových tabulek je neobvyklé. Změna se týká pouze pracovních zátěží, která zapisují do zdrojových tabulek a poté očekávají, že cachovaný DataFrame zobrazí nová data.
    • Pokud je vaše pracovní zátěž ovlivněna: Po zápisu do zdrojových tabulek z nich vytvořte nový DataFrame místo opětovného používání DataFramu uloženého v mezipaměti.

Dodatečné zdroje