Cache DataFrame pada komputasi serverless

Important

Fitur ini ada di Pratinjau Umum. Admin workspace dapat mengontrol akses ke caching DataFrame pada komputasi serverless dari halaman Pratinjau . Lihat Kelola Pratinjau Azure Databricks.

Pada komputasi serverless, Anda dapat menyimpan DataFrame ke cache dengan df.cache() atau df.persist() untuk menggunakan kembali hasil komputasi yang mahal dalam sesi Anda. Azure Databricks menghitung DataFrame saat Anda memanggil cache() dan mematerialisasi hasilnya sebagai snapshot. DataFrame dan DataFrames yang Anda bangun darinya kemudian akan membaca snapshot untuk sisa sesi Anda daripada menghitungnya ulang.

Requirements

  • pratinjau caching DataFrame pada komputasi serverless diaktifkan untuk workspace Anda (diaktifkan secara default). Admin workspace dapat menonaktifkannya dari halaman Pratinjau . Pratinjau tidak tersedia di workspace dengan profil keamanan kepatuhan diaktifkan. Lihat Mengelola pratinjau tingkat ruang kerja.
  • Notebook dan pekerjaan pada komputasi serverless harus menggunakan versi lingkungan 5 atau lebih tinggi.
  • Databricks Connect untuk Python harus 18.1.8 atau lebih tinggi, dan Databricks Connect untuk Scala harus 18.1.5 atau lebih tinggi.

Klien versi lama mendapatkan error CACHE_REQUIRES_NEWER_CLIENT_ON_SERVERLESS_GC.

Kapan menggunakan caching DataFrame pada komputasi serverless

Cache DataFrame pada komputasi serverless saat Anda membutuhkan:

  • Gunakan kembali hasil dari gabungan, agregasi, atau filter yang mahal beberapa kali dalam sesi yang sama.
  • Hitung micro-batch streaming sekali dalam sebuah foreachBatch fungsi, lalu tulisnya ke beberapa sink.
  • Latih atau sesuaikan beberapa model pembelajaran mesin pada data fitur yang sama yang sudah disiapkan.
  • Simpan snapshot yang stabil saat Anda menjalankan beberapa langkah analisis, meskipun tabel sumber berubah.

Lihat Praktik terbaik.

Cache DataFrame API pada komputasi serverless

Contoh berikut menyimpan ke cache pesanan selama satu hari yang digabungkan dengan data pelanggan, menghitung total pendapatan hari tersebut, menambahkan pendapatan berdasarkan wilayah ke tabel laporan, lalu membebaskan cache tersebut. Kedua hasil menggunakan snapshot yang di-cache alih-alih menjalankan join lagi.

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

Dalam deskripsi API berikut, df berarti DataFrame apa pun dalam sesi Anda, seperti oct_15_orders pada contoh sebelumnya.

df.cache()

Menghitung df langsung dan menyimpan hasil sebagai snapshot untuk sisa sesi Anda.

  • Mengembalikan: DataFrame yang sama yang di-cache, df, kini berbasis pada snapshot, bukan pada perhitungan pada tabel sumbernya. Lihat perilaku berikut.
  • Perilaku:
    • Menjalankan kueri DataFrame secara langsung dan mematerialisasi hasilnya sebagai snapshot sebelum pemanggilan selesai dan mengembalikan hasil.
    • Setelah panggilan, df dan DataFrame yang dikembalikan (df itu sendiri) didasarkan pada snapshot. Mereka tidak lagi terhubung dengan perhitungan pada tabel sumber, sehingga mereka membaca snapshot alih-alih menghitung ulang kueri.
    • DataFrame yang diturunkan dari df, langsung atau melalui DataFrame turunan lainnya, membaca snapshot secara otomatis sehingga tidak perlu menjalankan kueri asli lagi. Baca snapshot.
    • Snapshot tersebut bersifat lokal untuk sesi Anda. Hanya sesi yang menyimpannya di cache df yang dapat membacanya. Lihat Isolasi dan hak istimewa.
    • Snapshot berlangsung hingga sesi berakhir, paling lama selama tujuh hari. Azure Databricks kemudian secara otomatis membebaskan kembali ruang penyimpanannya di latar belakang. Memanggil df.unpersist() memungkinkan objek tersebut mengambil kembali penyimpanan lebih awal. Lihat Siklus Hidup dan batas waktu serta Penyimpanan dan pembersihan.
    • Jika komputasi df gagal, df.cache() memunculkan kesalahan dan df tidak di-cache.
    • Memanggil df.cache() pada DataFrame yang sudah di-cache tidak melakukan apa-apa. df tidak dihitung lagi.

Snapshot ditetapkan setelah Anda memanggil df.cache(). Data yang ditulis setelahnya ke tabel yang dibaca oleh df, dan perubahan skema pada tabel tersebut seperti kolom yang ditambahkan atau diganti namanya, tidak memengaruhinya. Untuk menghitung ulang dari data terbaru, bangun DataFrame kembali dari tabel sumber, dan cache DataFrame baru jika diperlukan.

Baca snapshot

Pada komputasi tanpa server, pencocokan cache didasarkan pada derivasi DataFrame. Setelah df.cache(), hanya DataFrame berikut yang membaca snapshot secara otomatis alih-alih menghitung ulang kueri pada tabel sumber:

  • DataFrame yang Anda cache df.
  • DataFrame yang berasal dari df, misalnya dengan select(), filter(), groupBy(), atau join().
  • DataFrame yang dirantai lebih lanjut dari DataFrame turunan tersebut.

DataFrame baru yang mengulangi kueri yang sama membaca tabel sumber, meskipun logikanya identik, karena tidak berasal dari df.

Ini membuat pencocokan cache menjadi eksplisit dan berada di bawah kendali Anda: DataFrame hanya membaca data yang di-cache ketika Anda menurunkannya dari DataFrame yang di-cache. Semua DataFrame lainnya membaca tabel sumber.

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

Karena df membaca snapshot, bukan DataFrame yang menjadi dasar pembangunannya, Anda tidak bisa merujuk kolom-kolom df melalui DataFrame tersebut. Lihat Batasan.

df.persist(storageLevel)

Alias dari df.cache() yang menerima tingkat penyimpanan.

  • Parameter:
    • storageLevel (opsional): Sebuah StorageLevel, seperti StorageLevel.DISK_ONLY. Komputasi serverless menerima tingkat penyimpanan apa pun dan mengabaikannya. Snapshot disimpan dengan cara yang sama untuk setiap tingkat penyimpanan, dan df.storageLevel mengembalikan StorageLevel.DISK_ONLY.

Nilai pengembalian dan perilaku sama dengan df.cache().

df.unpersist(blocking)

Melepaskan snapshot yang di-cache dari df dan menghancurkan DataFrame.

  • Parameter:
    • blocking (opsional): Diabaikan. df.unpersist() segera mengembalikan hasil untuk salah satu nilai.
  • Mengembalikan: DataFrame yang sama, df, kini telah dihancurkan.
  • Perilaku:
    • Menandai snapshot sebagai siap untuk diambil kembali. Azure Databricks kemudian menghapus data yang dicache dan mengambil kembali penyimpanan di latar belakang.
    • Menghancurkan df: df dan DataFrame yang sebelumnya diturunkan darinya tidak lagi dapat digunakan, dan setiap kueri berikutnya pada mereka akan menimbulkan CACHE_DATAFRAME_ACCESS_AFTER_UNCACHE. Jika Anda menyimpan DataFrame yang diturunkan dari df sebelum Anda memanggil df.unpersist(), DataFrame tersebut tetap dapat digunakan, karena memiliki snapshot sendiri.
    • Untuk terus bekerja dengan sumber data yang sama, bangun DataFrame baru dari sumber data asli, daripada menggunakan kembali DataFrame yang tidak dicache.
    • Memanggil df.unpersist() pada DataFrame yang tidak pernah di-cache, atau yang sudah di-uncache, adalah no-op.

Panggil df.unpersist() saat Anda tidak lagi membutuhkan data yang dicache, misalnya ketika tidak ada langkah selanjutnya di notebook atau pekerjaan Anda yang membacanya. Ini memungkinkan Azure Databricks untuk mengosongkan sumber daya penyimpanan lebih awal. Jangan gunakan df.unpersist() untuk menyegarkan data. Untuk bekerja dengan data terbaru, bangun DataFrame baru dari tabel sumber.

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

Mendapatkan tingkat penyimpanan df.

  • Pengembalian: StorageLevel.DISK_ONLY sementara df disimpan dalam cache. StorageLevel.NONE sebelum Anda cache dan setelah Anda memanggil 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

Untuk signature metode, lihat referensi PySpark untuk cache, persist, unpersist, dan storageLevel.

Siklus hidup dan batas waktu

Data yang di-cache hanya ada di dalam sesi Azure Databricks tempat Anda menyimpan cache tersebut. Ini menjadi tidak dapat diakses saat sesi berakhir, dan berlangsung paling lama tujuh hari. Setelah batas tujuh hari, DataFrame yang di-cache akan menimbulkan error alih-alih membaca tabel sumber lagi. Untuk melakukan cache lagi, mulai sesi baru.

Penyimpanan dan pembersihan

Azure Databricks mengelola penyimpanan untuk data cache secara otomatis. Data cache disimpan di cloud, dengan lokasi penyimpanan spesifik tergantung pada tipe workspace Anda:

  • Workspace klasik: Data yang disimpan dalam cache disimpan di akun penyimpanan workspace yang dikonfigurasi saat pembuatan workspace. Anda dapat mengonfigurasi enkripsi di tingkat akun penyimpanan.

Setelah data cache menjadi tidak dapat diakses, Azure Databricks secara otomatis mengambil kembali penyimpanan di latar belakang. Ini termasuk kasus di mana sesi berakhir karena terputus koneksi atau crash. Memanggil df.unpersist() memungkinkan Azure Databricks mengambil kembali penyimpanan lebih awal.

Isolasi dan hak istimewa

Setiap pengguna yang dapat menjalankan kode di komputasi serverless dapat menyimpan DataFrame dalam cache. Kamu tidak perlu hak istimewa tambahan.

Data cache menyediakan isolasi tingkat sesi. Hanya sesi yang menyimpan DataFrame dalam cache yang dapat membaca data yang di-cache. Pengguna lain tidak dapat mengaksesnya, termasuk pengguna lain dari notebook yang sama.

Data yang dicache berisi apa yang diizinkan untuk Anda baca saat Anda meng-cachenya. Perubahan izin, filter baris, dan masker kolom yang diterapkan pada tabel sumber setelahnya tidak berlaku untuk data yang dicache.

Praktik terbaik

  • Cache saat Anda membutuhkan snapshot yang stabil: Jika Anda menjalankan beberapa transformasi, agregasi, atau drill-down pada data hasil komputasi yang sama, snapshot memberikan baseline yang konsisten dan tidak berubah saat tabel sumber berubah.
  • Cache komputasi mahal, bukan pembacaan tabel biasa: df.cache() mematerialisasi hasil kueri, dan pembacaan selanjutnya memindai snapshot tersebut. Jika Anda men-cache pembacaan tabel biasa, seperti spark.table("main.sales.orders").cache(), pembacaan selanjutnya tetap memindai salinan penuh tabel, jadi cache hampir tidak memberi manfaat. Caching akan membuahkan hasil setelah pekerjaan mahal seperti join, agregasi, dan filter yang kompleks.
  • Jangan menyimpan data yang hanya Anda baca sekali dalam cache: df.cache() menghitung dan menyimpan hasilnya segera, yang memakan waktu dan penyimpanan. Jika Anda hanya membaca hasilnya sekali, biaya awal tidak sepadan.
  • Gunakan cache dengan menurunkan dari DataFrame yang di-cache: Untuk membaca snapshot, bangun operasi selanjutnya dari variabel DataFrame yang di-cache, misalnya df.select(...) atau df.filter(...). DataFrame independen yang dibangun dari komputasi yang sama pada tabel sumber tidak menggunakan cache.
  • Jangan gunakan cache untuk berbagi data lintas sesi atau antar pengguna: Data yang disimpan bersifat privat untuk sesi Anda. Sesi lain, buku catatan, run job, dan pengguna tidak bisa membacanya. Untuk membagikan hasil yang dihitung antar sesi atau dengan pengguna lain, tuliskan ke tabel permanen.
  • Pertahankan sesi dengan data cache di bawah tujuh hari: Lihat Batas Siklus Hidup dan Waktu. Jika alur kerja Anda membutuhkan data lebih lama, simpan ke tabel.
  • Panggil df.unpersist() saat Anda tidak lagi membutuhkan data yang dicache: Ini memungkinkan Azure Databricks untuk membebaskan ruang penyimpanan lebih awal. Setelah panggilan, DataFrame dan DataFrame-DataFrame yang diturunkan darinya tidak dapat digunakan.
  • Jangan gunakan df.unpersist() untuk menyegarkan data: df.unpersist() mengakhiri masa aktif snapshot. Untuk menangkap perubahan pada tabel sumber, bangun DataFrame baru dari tabel sumber.

Limitations

Caching DataFrame pada komputasi serverless memiliki keterbatasan berikut:

  • Nama dan tipe kolom: DataFrame berikut tidak dapat di-cache. Ganti nama atau cast kolom sebelum Anda cache, misalnya dengan .alias("total_amount").
    • DataFrame dengan nama kolom duplikat.
    • DataFrame dengan nama kolom yang berisi spasi atau karakter apa pun dalam ,;{}()=, seperti sum(amount) dari agregasi.
    • DataFrame dengan kolom interval.
    • DataFrame dengan array, peta, atau struct yang berisi nilai tipe NULL.
    • DataFrame tanpa kolom, atau hanya dengan kolom bertipe NULL.
  • Referensi kolom: Setelah Anda menyimpan cache DataFrame, Anda tidak dapat mereferensikan kolomnya melalui DataFrame yang menjadi dasar pembangunannya. Misalnya, setelah oct_15_orders = orders.join(customers, "customer_id") dan oct_15_orders.cache(), oct_15_orders.select(orders.amount) memunculkan CANNOT_RESOLVE_DATAFRAME_COLUMN. Gunakan oct_15_orders.amount atau "amount" sebagai gantinya.
  • API cache SQL dan katalog: Pernyataan cache SQL, seperti CACHE TABLE, dan metode cache tabel dari spark.catalog tidak didukung pada komputasi tanpa server. Lihat Pembatasan caching. Untuk menggunakan kembali hasil kueri di SQL, gunakan tabel sementara sesi-lokal.
  • Kueri skema informasi: Ketika banyak sesi meng-cache DataFrame di cache metastore, kueri pada information_schema.volumes dan information_schema.schemata bisa lambat atau habis waktu. Memfilter volumes berdasarkan katalog tidak membuat kueri menjadi lebih cepat. Kueri pada information_schema.tables tidak terpengaruh.
  • Azure Government regions: DataFrame caching tidak didukung pada serverless compute di Azure Government regions.

Migrasi dari Classic Compute

Untuk sebagian besar beban kerja, caching pada komputasi serverless memberikan hasil yang sama seperti pada komputasi klasik, dan kode yang ada berjalan tanpa perubahan. Tabel berikut mencantumkan perbedaannya.

Behavior Komputasi tanpa server Komputasi tradisional
Pencocokan tembolok Hanya DataFrame yang di-cache dan DataFrame yang diturunkan darinya yang secara otomatis menggunakan cache tersebut. Setiap query dengan bentuk rencana yang sama secara otomatis menggunakan cache.
Kesegaran data Snapshot konsisten yang diambil pada saat Anda memanggil df.cache(). Bervariasi: data cache diperbarui dalam beberapa kasus dan menyajikan snapshot dalam kasus lain.
Cakupan berbagi Pribadi untuk sesi Anda. Digunakan bersama antar sesi dalam klaster.
Materialisasi Eager: langsung dihitung saat Anda memanggil df.cache(). Lazy: dihitung pada aksi pertama pada DataFrame.
df.unpersist() Menghancurkan DataFrame dan melepaskan snapshot-nya secara deterministik. Melepaskan cache dalam memori. Penggunaan DataFrame di kemudian hari dapat mendapatkan data terbaru atau data yang sudah usang, tergantung pada produk dan sumber data.

Berikut ini adalah penjelasan dua perbedaan pertama secara lebih rinci:

  • Pencocokan cache:
    • Beban kerja yang terdampak perubahan: Sebagian besar beban kerja tidak terpengaruh. Jika Anda terus menggunakan variabel DataFrame yang di-cache, misalnya dengan df.select(...) atau df.filter(...), cache akan berfungsi seperti sebelumnya. Perubahan ini hanya memengaruhi beban kerja di mana DataFrame atau kueri SQL yang dibangun secara independen menggunakan kembali cache karena memiliki struktur rencana yang sama. Pada komputasi serverless, kueri tersebut membaca tabel sumber.
    • Jika beban kerja Anda terpengaruh: Gunakan variabel DataFrame yang di-cache di mana pun Anda membutuhkan hasil yang di-cache, daripada membangun kueri yang sama lagi.
  • Kesegaran data:
    • Beban kerja yang terdampak oleh perubahan ini: Sebagian besar beban kerja tidak terpengaruh, karena membaca data cache kembali setelah menulis ke tabel sumbernya jarang terjadi. Perubahan ini hanya memengaruhi beban kerja yang menulis ke tabel sumber dan kemudian mengharapkan DataFrame yang di-cache menampilkan data baru.
    • Jika beban kerja Anda terpengaruh: Setelah Anda menulis ke tabel sumber, bangun DataFrame baru dari tabel tersebut daripada menggunakan ulang yang sudah di-cache.

Sumber daya tambahan