Yerel yürütme altyapısında Python UDF'leri, Scala UDF'leri ve karmaşık veri türleri

Microsoft Fabric'daki yerel yürütme altyapısı artık Python kullanıcı tanımlı işlevleri (UDF), Scala UDF'lerini ve karmaşık veri türlerini (diziler, haritalar ve yapılar) destekliyor. Bu özellikler performansdan ödün vermeden etkileyici Spark uygulamaları yazmanızı sağlar.

Python UDF desteği

Python, veri mühendisliği ve veri biliminin en popüler dillerinden biridir. Geçmişte Python UDF'ler, JVM ile Python çalışan işlemleri arasındaki serileştirme maliyetleri nedeniyle Spark'ta önemli ek yük getirirdi. Yerel yürütme altyapısı bu pahalı geçişleri en aza indirerek kod değişikliği olmadan daha hızlı yürütmeyi sağlar.

Python UDF'ler yerel yürütme altyapısında nasıl çalışır?

Geleneksel spark yürütme modelinde Python UDF yürütme şunları içerir:

  1. Spark'ın iç biçiminden veri dönüştürme.
  2. Serileştirme ve Python worker süreçlerine aktarımı.
  3. Python UDF yürütme
  4. Sonuçların JVM'ye geri serileştirilmesi.
  5. Spark yürütmeyi sürdürür.

Bu çalışma zamanları arası veri aktarımı, serileştirme ve serileştirmeyi geri alma maliyetlerine, CPU verimsizliğine ve sütun bazlı yürütme ardışık düzenlerinin bozulmasına yol açar. Yerel yürütme altyapısı, veri aktarım yolunu iyileştirerek ve mümkün olduğunda vektörleştirilmiş işlemeyi koruyarak bu ek yükü azaltır.

Desteklenen Python UDF türleri

Yerel yürütme altyapısı aşağıdakileri destekler:

  • Scalar UDF: udf() ile kaydedilen satır satır Python işlevleri.
  • Vektörleştirilmiş (Pandas) UDF'ler: Verimli veri aktarımı için Apache Arrow kullanan, veri grupları üzerinde çalışan @pandas_udf ile dekore edilmiş işlevler.

Vektörleştirilmiş UDF'ler doğal olarak yerel yürütme altyapısının sütunlu işleme modeliyle uyumlu olduğundan en büyük performans artışlarını görür.

Örnek: Vektörleştirilmiş Python UDF

import pandas as pd
from pyspark.sql.functions import pandas_udf
from pyspark.sql.types import DoubleType

@pandas_udf(DoubleType())
def calculate_discount(price: pd.Series, rate: pd.Series) -> pd.Series:
    return price * (1 - rate)

df = spark.table("sales.transactions")
result = df.withColumn("discounted_price", calculate_discount(df.price, df.discount_rate))
result.show()

Yerel yürütme altyapısını etkinleştirmenin ötesinde ek yapılandırma gerekmez. Mevcut Python UDF'ler otomatik olarak avantaj sağlar.

Scala UDF desteği

Yerel yürütme altyapısı, Scala UDF'lerini de hızlandırır. Scala UDF'leri JVM'de yerel olarak çalıştığından, altyapı desteklenen işlemleri vektörleştirilmiş C++ yürütme yoluna boşaltırken Scala UDF değerlendirmesini aynı çalışma zamanında verimli tutabilir.

Örnek: Scala UDF

import org.apache.spark.sql.functions.udf

val toUpperCase = udf((s: String) => s.toUpperCase)
val df = spark.table("catalog.customers")
val result = df.withColumn("name_upper", toUpperCase(df("name")))
result.show()

Desteklenen veri türlerinde çalışan Scala UDF'leri, yerel yürütme altyapısı etkinleştirildiğinde kod değişikliği olmadan hızlandırılır.

Karmaşık veri türleri desteği

Modern göl evi mimarileri yarı yapılandırılmış ve iç içe yerleştirilmiş verilere bağlıdır. Yerel yürütme altyapısı artık aşağıdakiler için iyileştirilmiş destek sağlar:

Veri türü Description Örnek kullanım örneği
Dizi Sıralı öğe koleksiyonu Olay etiketleri, ürün kategorileri
Harita Anahtar değer çiftleri Yapılandırma özellikleri, meta veriler
Struct Farklı türlerde adlandırılmış alanlar İç içe müşteri kayıtları, adres nesneleri

Karmaşık türler için desteklenen işlemler

Yerel yürütme altyapısı karmaşık veri türlerinde yaygın işlemleri hızlandırır:

  • Dizi işlevleri: explode, array_contains, size, flatten, transform
  • Harita işlevleri: map_keys, map_values, element_at
  • Yapı erişimi: Noktalı notasyon alanı erişimi, getField
  • İç içe kombinasyonlar: Yapı dizileri, dizi değerli eşlemler

Örnek: Diziler ve yapılarla çalışma

from pyspark.sql.functions import explode, col, size

# Read data with nested schema
df = spark.table("events.telemetry")

# Operations on arrays - accelerated by native engine
result = (df
    .filter(size(col("tags")) > 0)
    .select(
        col("event_id"),
        col("metadata.source"),  # Struct field access
        explode(col("tags")).alias("tag")
    )
)
result.show()

Örnek: Haritalarla çalışma

from pyspark.sql.functions import map_keys, map_values, col

df = spark.table("config.settings")

# Map operations - accelerated by native engine
result = (df
    .select(
        col("setting_id"),
        map_keys(col("properties")).alias("keys"),
        map_values(col("properties")).alias("values")
    )
)
result.show()

Performans sonuçları

İç karşılaştırma, Python UDF'leri ve karmaşık veri türlerini kullanan iş yüklerinde önemli iyileştirmeler gösterir:

İş yükü türü Performans iyileştirmesi
Vektörleştirilmiş Python UDF'ler 5,76 kata kadar daha hızlı
Skaler Python UDF'ler 1,08 kata kadar daha hızlı
TPC-DS uçtan uca (karmaşık türlerle) 2,35 kata kadar daha hızlı

Bu kazançlar daha az serileştirme yükü, geliştirilmiş vektörleştirme ve uçtan uca sütunlu yürütmeden kaynaklanır.

Gelişmiş göl evi desenlerinin avantajları

Karmaşık veri türü hızlandırma özellikle şunlar için önemlidir:

  • Z-ORDER iyileştirmesi: İç içe sütunlar iyileştirilmiş veri düzenine katılır.
  • Liquid clustering: Karmaşık türdeki sütunlar, düzleştirme gerektirmeden kümelemeden yararlanır.
  • Yarı yapılandırılmış analiz: JSON yükleri ve olay akışları doğal sorgulama için iç içe yerleştirilmiş olarak kalır.
  • Olay odaklı mimariler: Telemetri ve IoT verileri hiyerarşik yapılarını korur.

Verileri düzleştirme veya işlem hatlarını performans için yeniden yapılandırmak yerine, yüksek yürütme verimliliğini korurken karmaşık şemalarla doğal olarak çalışın.

Özelliği etkinleştirme

Yerel yürütme altyapısı etkinleştirildiğinde Python UDF, Scala UDF ve karmaşık veri türü desteği kullanılabilir. Ek yapılandırma gerekmez.

Yerel yürütme altyapısını etkinleştirmek için bkz. Doku Veri Mühendisliği için yerel yürütme altyapısı.

Prerequisites

Sınırlamalar

  • Tüm Python kitaplıkları vektörleştirilmiş yolda desteklenmez. Rastgele Python nesne serileştirmesi gerektiren kitaplıklar geri dönüş tetikleyebilir.
  • Derin iç içe yerleştirilmiş karmaşık türler (örneğin, yapı eşleme dizileri) belirli işlemler için JVM altyapısına geri dönebilir.
  • ANSI modu yerel yürütme altyapısında desteklenmez.