Büyük veri setleriyle çalışırken Pandas’ın performans sınırlarına mı takılıyorsunuz? DuckDB, bellek dışı sorunları aşarak ve karmaşık SQL sorgularını Python ortamınızda hızla çalıştırarak Pandas ile veri analizi iş akışınızı devrim niteliğinde tamamlar. Bu makale, her iki aracın güçlü yanlarını birleştirerek büyük ölçekli veri analizini nasıl daha verimli hale getirebileceğinizi adım adım açıklıyor.
Büyük Veri Analizi Neden Zorlu Bir Görev Haline Geldi?
Günümüz dünyasında veri, adeta yeni petrol olarak kabul ediliyor ve şirketler, iş süreçlerini optimize etmek, müşteri davranışlarını anlamak ve geleceğe yönelik stratejiler geliştirmek için bu verileri etkin bir şekilde analiz etmeye çalışıyor. Ancak, veri hacmi ve karmaşıklığı hızla artarken, geleneksel veri analizi araçları genellikle yetersiz kalabiliyor. Özellikle Python ekosisteminde veri bilimcilerin ve analistlerin vazgeçilmezi olan Pandas, milyonlarca hatta milyarlarca satırlık veri setleriyle karşılaşıldığında performans darboğazları yaşayabiliyor.
Pandas’ın gücü, bellek içi (in-memory) çalışmasından gelir. Bu, küçük ve orta ölçekli veri setleri için inanılmaz bir hız ve esneklik sunarken, veri seti makinenizin RAM’ini aştığında ciddi sorunlara yol açabilir. Bellek dışı (out-of-memory) hataları, yavaş çalışan sorgular ve karmaşık veri dönüşümlerinin uzun sürmesi, veri analizi süreçlerini kabusa çevirebilir. Dolayısıyla, analistler, büyük veri setleriyle başa çıkmak için daha güçlü, daha ölçeklenebilir ve daha performanslı çözümler aramaya başlıyorlar. İşte tam bu noktada DuckDB gibi yeni nesil araçlar devreye giriyor ve Pandas’ın yeteneklerini tamamlayarak büyük veri analizi dünyasına yeni bir soluk getiriyor.
Bu makalede, Pandas’ın neden bu sınırlarla karşılaştığını ve DuckDB’nin bu sınırlamaları nasıl ortadan kaldırdığını detaylı bir şekilde inceleyeceğiz. Ayrıca, her iki aracı birlikte kullanarak nasıl daha verimli ve güçlü veri analizi iş akışları oluşturabileceğinizi, gerçek dünya senaryoları ve kod örnekleriyle adım adım göstereceğiz. Amacımız, veri analizi yolculuğunuzda size rehberlik etmek ve hem yeni başlayanlara hem de deneyimli veri profesyonellerine ilham vermektir. Büyük veri setleriyle çalışırken karşılaştığınız zorlukları aşmak ve analizlerinizi bir sonraki seviyeye taşımak için hazır mısınız?
Pandas ve DuckDB Temelleri: Hangi Araç Neye Yarar?
Büyük ölçekli veri analizi yolculuğumuza başlamadan önce, temel taşlarımız olan Pandas ve DuckDB’yi daha yakından tanıyalım. Her iki araç da veri manipülasyonu ve analizi için tasarlanmış olsa da, felsefeleri ve en iyi kullanıldıkları senaryolar farklılık gösterir. Bu bölüm, her birinin güçlü yönlerini, sınırlamalarını ve birbirlerini nasıl tamamladıklarını anlamamıza yardımcı olacak.
Pandas Nedir ve Neden Popülerdir?
Pandas, Python programlama dili için geliştirilmiş, veri manipülasyonu ve analizi için açık kaynaklı bir kütüphanedir. Özellikle “DataFrame” adı verilen, tablo benzeri veri yapıları sayesinde popülerlik kazanmıştır. Bu DataFrameler, SQL’deki tablolara veya Excel’deki çalışma sayfalarına benzer bir yapıya sahiptir ve etiketli sütunlar ve indekslenmiş satırlardan oluşur. Pandas’ın popülerliğinin arkasındaki temel nedenler şunlardır:
- Kullanım Kolaylığı: Sezgisel API’si sayesinde veri yükleme, temizleme, dönüştürme ve analiz etme işlemleri oldukça basittir.
- Zengin Fonksiyon Seti: Veri filtreleme, sıralama, gruplama, birleştirme (merge/join), zaman serisi analizi ve eksik veri işleme gibi çok çeşitli operasyonları destekler.
- Python Ekosistemiyle Entegrasyon: NumPy, SciPy, Matplotlib ve Scikit-learn gibi diğer popüler Python kütüphaneleriyle sorunsuz bir şekilde entegre olur. Bu, veri bilimcilerin uçtan uca analiz projelerini tek bir ortamda yürütmelerini sağlar.
- Hızlı Geliştirme: Prototipleme ve keşifsel veri analizi (EDA) için idealdir, çünkü verilerle hızlıca etkileşim kurmayı ve sonuçları görselleştirmeyi kolaylaştırır.
Ancak, Pandas’ın bellek içi çalışma prensibi, onu büyük veri setleri için bir darboğaz haline getirebilir. Veri seti RAM’e sığmadığında, performans düşer ve bellek hataları ortaya çıkar. Bu durum, analistleri alternatif çözümler aramaya iter.
DuckDB Nedir ve Nasıl Fark Yaratır?
DuckDB, analitik iş yükleri (OLAP) için tasarlanmış, gömülü (embedded), bellek içi ve disk tabanlı bir sütun tabanlı (columnar) veritabanı yönetim sistemidir. “Gömülü” olması, ayrı bir sunucu süreci gerektirmediği anlamına gelir; tıpkı SQLite gibi, uygulamanızın içinde çalışır. DuckDB’nin temel özellikleri ve fark yaratan yönleri şunlardır:
- Sütun Tabanlı Depolama: Verileri satır yerine sütun bazında depolar. Bu, analitik sorgularda (örneğin, ortalama alma, toplama) yalnızca ilgili sütunların okunmasını sağlayarak I/O ve bellek kullanımını optimize eder.
- SQL Desteği: Standart SQL sözdizimini destekler. Bu, SQL bilen herkesin DuckDB’yi kolayca kullanabileceği anlamına gelir ve karmaşık veri manipülasyonları için güçlü bir dil sunar.
- OLAP Odaklı Performans: Agregasyonlar, birleştirmeler ve filtreleme gibi analitik sorgular için özel olarak optimize edilmiştir. Büyük veri setlerinde Pandas’tan kat kat daha hızlı performans gösterebilir.
- Bellek ve Disk Yönetimi: Veri seti RAM’i aştığında dahi sorunsuz çalışabilir. Gerekirse verileri otomatik olarak diske taşır ve bellek dışı hatalarını önler.
- Python Entegrasyonu: Python API’si sayesinde Pandas DataFrameleri ile doğrudan etkileşim kurabilir. Bu, Pandas kullanıcıları için geçişi oldukça kolaylaştırır.
- Dosya Formatı Desteği: CSV, Parquet, JSON gibi çeşitli dosya formatlarından doğrudan sorgulama yapabilir, bu da ETL süreçlerini basitleştirir.
Özetle, Pandas veri keşfi ve manipülasyonu için harika bir araçken, DuckDB büyük ölçekli, analitik SQL sorguları için optimize edilmiş bir güç merkezidir. İkisi bir araya geldiğinde, küçükten büyüğe her türlü veri analizi ihtiyacını karşılayabilecek güçlü ve esnek bir iş akışı oluştururlar.
Aşağıdaki tablo, iki aracın temel özelliklerini karşılaştırmaktadır:
| Özellik | Pandas | DuckDB |
|---|---|---|
| Ana Kullanım Alanı | Veri Keşfi, Manipülasyonu, Küçük-Orta Ölçekli Analiz | Büyük Ölçekli Analitik Sorgular (OLAP), ETL |
| Veri Depolama | Bellek İçi (Row-oriented) | Bellek İçi ve Disk Tabanlı (Column-oriented) |
| Sorgu Dili | Python API | SQL (Standart) |
| Bellek Yönetimi | RAM’e bağımlı, bellek dışı hataları olası | Otomatik disk taşması, bellek dışı hataları nadir |
| Entegrasyon | Python ekosistemiyle güçlü | Python, R, Java vb. ile güçlü API’ler |
| Performans | Küçük-orta veri setlerinde hızlı | Büyük veri setlerinde analitik sorgularda çok hızlı |
Pandas’ın Sınırlarını Aşmak: DuckDB Ne Zaman Devreye Girer?
Pandas, veri bilimciler ve analistler için şüphesiz bir devrim niteliğindedir. Ancak, veri hacimleri arttıkça, Pandas’ın bellek içi çalışma prensibi ve Python tabanlı operasyonlarının doğası gereği bazı kısıtlamalar ortaya çıkar. Bu kısıtlamalar, özellikle büyük veri setleriyle çalışırken verimliliği ve performansı olumsuz etkileyebilir. Peki, DuckDB bu senaryolarda nasıl bir kurtarıcı rolü üstlenir?
Pandas’ın karşılaştığı başlıca zorluklar şunlardır:
- Bellek Dışı (Out-of-Memory) Hataları: Veri setinin boyutu, bilgisayarın RAM’ini aştığında Pandas DataFrame’leri belleğe yükleyemez ve “MemoryError” hatası verir. Bu, özellikle gigabaytlarca hatta terabaytlarca veriyle çalışırken sıkça karşılaşılan bir durumdur.
- Büyük Veri Setlerinde Performans Düşüşü: Veri seti büyüdükçe, filtreleme, gruplama, birleştirme (join) gibi operasyonlar önemli ölçüde yavaşlar. Pandas’ın tek çekirdekli yapısı ve Python’ın Global Interpreter Lock (GIL) kısıtlaması, paralel işlem yeteneklerini sınırlar.
- Karmaşık SQL Benzeri Sorguların Python’da Zorluğu: SQL’deki gibi karmaşık birleştirme, alt sorgu veya pencere fonksiyonları (window functions) gibi operasyonları Pandas’ın API’si ile ifade etmek bazen hantal ve okunaksız kodlara yol açabilir. SQL bilenler için bu, verimsiz bir süreçtir.
İşte bu gibi durumlarda DuckDB, sahneye çıkarak Pandas’ın zayıf kaldığı noktaları kapatır. DuckDB’nin sütun tabanlı mimarisi ve disk tabanlı çalışma yeteneği, bellek dışı hatalarını ortadan kaldırır. Ayrıca, analitik sorgular için optimize edilmiş sorgu motoru, büyük veri setlerinde dahi inanılmaz hızlar sunar. SQL’in gücünü doğrudan Python ortamınıza taşıyarak, karmaşık veri manipülasyonlarını çok daha kolay ve verimli hale getirir.
Gerçek Dünya Senaryosu: Milyonlarca Satırlık CSV Dosyasını İşleme
Bir e-ticaret şirketinde çalıştığınızı ve son bir yılın tüm sipariş verilerini içeren 5 GB’lık bir CSV dosyanız olduğunu varsayalım. Bu dosya, 50 milyondan fazla satır içeriyor ve her satırda sipariş ID’si, müşteri ID’si, ürün ID’si, miktar, fiyat, tarih gibi bilgiler bulunuyor. Göreviniz, aylık toplam satışları ve en çok satan ilk 10 ürünü bulmak.
Pandas ile Yaklaşım (ve Zorlukları):
import pandas as pd
import time
# Dosya yolu
file_path = 'buyuk_siparis_verileri.csv' # Varsayımsal 5GB dosya
# Adım 1: CSV dosyasını Pandas DataFrame'e yükleme
start_time = time.time()
try:
df_pandas = pd.read_csv(file_path)
print(f"Pandas ile yükleme süresi: {time.time() - start_time:.2f} saniye")
# Adım 2: Aylık toplam satışları hesaplama
df_pandas['siparis_tarihi'] = pd.to_datetime(df_pandas['siparis_tarihi'])
df_pandas['ay'] = df_pandas['siparis_tarihi'].dt.to_period('M')
aylik_satislar = df_pandas.groupby('ay')['fiyat'].sum()
print(f"Pandas ile aylık satış hesaplama süresi: {time.time() - start_time:.2f} saniye")
# Adım 3: En çok satan ilk 10 ürünü bulma
df_pandas['toplam_gelir'] = df_pandas['miktar'] * df_pandas['fiyat']
en_cok_satanlar = df_pandas.groupby('urun_id')['toplam_gelir'].sum().nlargest(10)
print(f"Pandas ile en çok satanlar hesaplama süresi: {time.time() - start_time:.2f} saniye")
except MemoryError:
print("Hata: Pandas, veri setini belleğe yükleyemedi. Bellek dışı hatası.")
except Exception as e:
print(f"Bir hata oluştu: {e}")
Bu senaryoda, 5 GB’lık bir CSV dosyasını Pandas’a yüklemek bile çoğu makinede “MemoryError” ile sonuçlanacaktır. Eğer yükleyebilseydik bile, gruplama ve toplama işlemleri çok uzun sürecekti. İşte burada DuckDB, doğrudan CSV dosyasından sorgulama yeteneği ve optimize edilmiş motoruyla devreye girer.
import duckdb
import time
# Dosya yolu
file_path = 'buyuk_siparis_verileri.csv' # Varsayımsal 5GB dosya
# Adım 1: DuckDB ile doğrudan CSV dosyasından sorgulama
start_time = time.time()
conn = duckdb.connect(database=':memory:', read_only=False) # Bellek içi DuckDB bağlantısı
# Aylık toplam satışları hesaplama
query_aylik_satislar = f"""
SELECT
strftime(siparis_tarihi, '%Y-%m') AS ay,
SUM(fiyat) AS toplam_satis
FROM '{file_path}'
GROUP BY 1
ORDER BY 1;
"""
aylik_satislar_duckdb = conn.execute(query_aylik_satislar).fetchdf()
print(f"DuckDB ile aylık satış hesaplama süresi: {time.time() - start_time:.2f} saniye")
print("Aylık Satışlar (DuckDB):")
print(aylik_satislar_duckdb.head())
# En çok satan ilk 10 ürünü bulma
query_en_cok_satanlar = f"""
SELECT
urun_id,
SUM(miktar * fiyat) AS toplam_gelir
FROM '{file_path}'
GROUP BY urun_id
ORDER BY toplam_gelir DESC
LIMIT 10;
"""
en_cok_satanlar_duckdb = conn.execute(query_en_cok_satanlar).fetchdf()
print(f"DuckDB ile en çok satanlar hesaplama süresi: {time.time() - start_time:.2f} saniye")
print("En Çok Satan İlk 10 Ürün (DuckDB):")
print(en_cok_satanlar_duckdb)
conn.close()
DuckDB, CSV dosyasını belleğe tamamen yüklemeden, doğrudan dosya üzerinden sorgulama yapabilme yeteneği sayesinde “MemoryError” sorununu ortadan kaldırır. Ayrıca, optimize edilmiş SQL motoru sayesinde, bu tür agregasyonları Pandas’tan çok daha hızlı bir şekilde gerçekleştirir. Bu örnek, DuckDB’nin büyük veri setleriyle çalışırken ne kadar kritik bir rol oynayabileceğini açıkça göstermektedir. Pandas’ın yeteneklerini tamamlayarak, veri analistlerinin daha önce mümkün olmayan ölçeklerde çalışmasına olanak tanır.
DuckDB ile Pandas Veri Çerçevelerini Nasıl Sorgularız?
DuckDB’nin en etkileyici özelliklerinden biri, mevcut Pandas DataFrameleri ile sorunsuz bir şekilde entegre olabilmesidir. Bu entegrasyon, Pandas’ın esnek veri manipülasyon yeteneklerini DuckDB’nin yüksek performanslı SQL motoruyla birleştirmenizi sağlar. Böylece, küçük ölçekli veri keşfi için Pandas’ı kullanırken, büyük ve karmaşık sorgular için DuckDB’ye geçiş yapabilir ve sonuçları kolayca Pandas’a geri alabilirsiniz. Bu bölüm, bu entegrasyonu adım adım nasıl gerçekleştireceğinizi ve kod örnekleriyle nasıl kullanacağınızı açıklayacaktır.
Adım Adım Entegrasyon: DuckDB ve Pandas İş Akışı
DuckDB’nin Python API’si, Pandas DataFrameleri ile çalışmayı son derece kolaylaştırır. Temel olarak iki ana yöntemle bu entegrasyonu sağlayabiliriz:
duckdb.sql()Fonksiyonu: Bu fonksiyon, doğrudan SQL sorguları çalıştırmanıza olanak tanır ve sorgu içinde Pandas DataFramelerine referans verebilirsiniz. DuckDB, sorguyu çalıştırırken DataFrame’i geçici bir tablo gibi görür.duckdb.from_df()Metodu: Bu metot, bir Pandas DataFrame’i doğrudan DuckDB’nin anlayabileceği bir tablo nesnesine dönüştürür. Bu tablo nesnesi üzerinde daha sonra SQL sorguları çalıştırılabilir.
Her iki yöntem de oldukça güçlüdür ve kullanım senaryonuza göre tercih edilebilir. Genellikle, hızlı ve tek seferlik sorgular için duckdb.sql() daha pratikken, daha karmaşık veya çok adımlı SQL operasyonları için duckdb.connect() ile bir bağlantı oluşturup DataFrame’i kaydetmek daha esnek olabilir.
Kod Örnekleri: DataFrame Oluşturma, DuckDB ile Sorgulama, Sonuçları Pandas’a Geri Alma
Şimdi somut bir örnek üzerinden bu entegrasyonu inceleyelim. Diyelim ki elimizde satış verilerini içeren bir Pandas DataFrame var ve bu DataFrame üzerinde karmaşık bir gruplama ve sıralama işlemi yapmak istiyoruz.
import pandas as pd
import duckdb
import time
# Adım 1: Örnek bir Pandas DataFrame oluşturma
data = {
'siparis_id': range(1, 1000001),
'musteri_id': [f'C{i % 1000 + 1}' for i in range(1000000)],
'urun_kategori': [f'Kategori_{i % 50 + 1}' for i in range(1000000)],
'fiyat': [round(i * 0.1 + 10, 2) for i in range(1000000)],
'adet': [i % 5 + 1 for i in range(1000000)],
'siparis_tarihi': pd.to_datetime(pd.date_range('2022-01-01', periods=1000000, freq='H'))
}
df_pandas = pd.DataFrame(data)
print(f"Oluşturulan Pandas DataFrame boyutu: {len(df_pandas)} satır")
# Adım 2: Pandas ile işlem yapalım (Karşılaştırma için)
start_time_pandas = time.time()
pandas_result = df_pandas.groupby('urun_kategori').agg(
toplam_satis=('fiyat', 'sum'),
ortalama_adet=('adet', 'mean'),
toplam_adet=('adet', 'sum')
).sort_values(by='toplam_satis', ascending=False).head(10)
print(f"Pandas ile gruplama ve sıralama süresi: {time.time() - start_time_pandas:.4f} saniye")
print("Pandas Sonucu (İlk 5):")
print(pandas_result.head())
# Adım 3: DuckDB ile aynı işlemi yapalım
start_time_duckdb = time.time()
# Yöntem A: duckdb.sql() kullanarak doğrudan DataFrame'i sorgulama
# DuckDB, 'df_pandas' değişkenini otomatik olarak bir tablo olarak algılar
duckdb_result_a = duckdb.sql("""
SELECT
urun_kategori,
SUM(fiyat) AS toplam_satis,
AVG(adet) AS ortalama_adet,
SUM(adet) AS toplam_adet
FROM df_pandas
GROUP BY urun_kategori
ORDER BY toplam_satis DESC
LIMIT 10;
""").fetchdf() # Sonucu tekrar Pandas DataFrame olarak al
print(f"DuckDB (duckdb.sql) ile gruplama ve sıralama süresi: {time.time() - start_time_duckdb:.4f} saniye")
print("DuckDB Sonucu (duckdb.sql - İlk 5):")
print(duckdb_result_a.head())
# Yöntem B: Bağlantı oluşturup DataFrame'i kaydetme (daha büyük ve karmaşık senaryolar için)
start_time_duckdb_conn = time.time()
conn = duckdb.connect(database=':memory:', read_only=False) # Bellek içi veritabanı
conn.register('my_sales_data', df_pandas) # DataFrame'i 'my_sales_data' adıyla kaydet
duckdb_result_b = conn.execute("""
SELECT
urun_kategori,
SUM(fiyat) AS toplam_satis,
AVG(adet) AS ortalama_adet,
SUM(adet) AS toplam_adet
FROM my_sales_data
GROUP BY urun_kategori
ORDER BY toplam_satis DESC
LIMIT 10;
""").fetchdf()
print(f"DuckDB (conn.register) ile gruplama ve sıralama süresi: {time.time() - start_time_duckdb_conn:.4f} saniye")
print("DuckDB Sonucu (conn.register - İlk 5):")
print(duckdb_result_b.head())
conn.close()
Yukarıdaki örnekte, 1 milyon satırlık bir DataFrame üzerinde basit bir gruplama ve sıralama işlemi yaptık. DuckDB’nin, bu tür analitik sorgularda Pandas’tan daha hızlı sonuç verdiğini göreceksiniz. Özellikle veri seti büyüdükçe bu performans farkı katlanarak artar. DuckDB’nin SQL motoru, bu tür sorguları çok daha verimli bir şekilde optimize eder ve çalıştırır.
Sonuç olarak, Pandas DataFrame’lerinizle DuckDB’yi entegre etmek, büyük veri analizi projelerinizde size hem hız hem de esneklik kazandırır. Veri keşfi için Pandas’ın rahatlığını korurken, performans kritik operasyonlar için SQL’in gücünden ve DuckDB’nin hızından faydalanabilirsiniz.
Gerçek Dünya Uygulamaları: Büyük Ölçekli ETL ve Analiz Senaryoları
DuckDB ve Pandas’ın birleşimi, özellikle büyük ölçekli Veri Çıkarma, Dönüştürme ve Yükleme (ETL) süreçlerinde ve karmaşık analitik senaryolarda gerçek bir oyun değiştirici olabilir. Geleneksel olarak, bu tür işlemler için büyük veritabanı sistemleri veya dağıtık işlem çerçeveleri (Spark gibi) gerekebilirken, DuckDB, tek bir makinede dahi bu görevleri şaşırtıcı bir verimlilikle yerine getirebilir. Bu bölümde, DuckDB’nin bu alandaki gücünü gösteren iki vaka analizini inceleyeceğiz.
Vaka Analizi 1: Zaman Serisi Verilerinin DuckDB ile Hızlı Agregasyonu
Bir finansal analiz şirketinde çalıştığınızı ve son 5 yıla ait, her saniye güncellenen hisse senedi fiyat verilerini (yaklaşık 100 milyon satır) içeren büyük bir Parquet dosyanız olduğunu varsayalım. Göreviniz, bu verilerden günlük ortalama, en yüksek ve en düşük fiyatları hesaplamak ve ayrıca 7 günlük hareketli ortalamaları (moving averages) bulmaktır.
Pandas ile Zorluk: Bu kadar büyük bir Parquet dosyasını doğrudan Pandas’a yüklemek bile bellek sorunlarına yol açabilir. Yükleyebilseniz bile, tarih-saat dönüşümleri, gruplamalar ve özellikle pencere fonksiyonları (hareketli ortalama gibi) çok uzun sürebilir ve makinenizi aşırı zorlayabilir.
DuckDB ile Çözüm: DuckDB, Parquet dosyalarını doğrudan sorgulama yeteneği ve optimize edilmiş pencere fonksiyonu desteği sayesinde bu görevi çok daha verimli hale getirir.
import duckdb
import pandas as pd
import time
import os
# Varsayımsal Parquet dosyası oluşturma (Gerçek senaryoda bu dosya zaten mevcut olacaktır)
# Bu kısım sadece örnek veriyi oluşturmak içindir, gerçek kullanımda doğrudan okuyacaksınız.
if not os.path.exists('buyuk_hisse_verileri.parquet'):
print("Parquet dosyası oluşturuluyor (Bu biraz zaman alabilir)...")
num_rows = 100_000_000 # 100 milyon satır
dates = pd.to_datetime(pd.date_range('2019-01-01', periods=num_rows, freq='S'))
prices = pd.Series(range(num_rows)).apply(lambda x: 100 + (x % 100) * 0.1 + (x % 50) * 0.05).round(2)
df_large = pd.DataFrame({
'timestamp': dates,
'hisse_kodu': ['AAPL'] * num_rows, # Basitlik için tek hisse
'fiyat': prices
})
df_large.to_parquet('buyuk_hisse_verileri.parquet', index=False)
print("Parquet dosyası oluşturuldu.")
else:
print("Parquet dosyası zaten mevcut.")
file_path_parquet = 'buyuk_hisse_verileri.parquet'
conn = duckdb.connect(database=':memory:', read_only=False)
start_time_duckdb = time.time()
# Günlük ortalama, en yüksek ve en düşük fiyatları hesaplama
daily_summary_query = f"""
SELECT
CAST(timestamp AS DATE) AS tarih,
AVG(fiyat) AS gunluk_ortalama,
MAX(fiyat) AS gunluk_yuksek,
MIN(fiyat) AS gunluk_dusuk
FROM '{file_path_parquet}'
GROUP BY 1
ORDER BY 1;
"""
daily_summary_df = conn.execute(daily_summary_query).fetchdf()
print(f"DuckDB ile günlük özet hesaplama süresi: {time.time() - start_time_duckdb:.2f} saniye")
print("Günlük Özet (İlk 5):")
print(daily_summary_df.head())
# 7 günlük hareketli ortalamayı hesaplama (Pencere Fonksiyonu)
start_time_ma_duckdb = time.time()
moving_average_query = f"""
SELECT
CAST(timestamp AS DATE) AS tarih,
AVG(fiyat) AS gunluk_ortalama,
AVG(fiyat) OVER (ORDER BY CAST(timestamp AS DATE) ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS yedi_gunluk_hareketli_ortalama
FROM '{file_path_parquet}'
GROUP BY 1
ORDER BY 1;
"""
moving_average_df = conn.execute(moving_average_query).fetchdf()
print(f"DuckDB ile 7 günlük hareketli ortalama hesaplama süresi: {time.time() - start_time_ma_duckdb:.2f} saniye")
print("7 Günlük Hareketli Ortalama (İlk 5):")
print(moving_average_df.head())
conn.close()
DuckDB, Parquet dosyasını optimize edilmiş bir şekilde okur ve SQL’in güçlü pencere fonksiyonları sayesinde hareketli ortalama gibi karmaşık zaman serisi analizlerini çok hızlı bir şekilde gerçekleştirir. Sonuçları doğrudan Pandas DataFrame olarak alarak daha ileri görselleştirmeler veya modelleme için kullanabilirsiniz.
Vaka Analizi 2: Çoklu Veri Kaynaklarından Birleştirme (JOIN) ve Temizleme
Bir veri mühendisi olarak, üç farklı kaynaktan gelen verileri birleştirip temizlemeniz gerekiyor:
musteri_bilgileri.csv(10 milyon müşteri, isim, adres, kayıt tarihi)urun_katalogu.parquet(500 bin ürün, ürün adı, kategori, fiyat)siparis_detaylari.json(20 milyon sipariş, müşteri ID, ürün ID, miktar, tarih)
Göreviniz, bu üç veri setini birleştirerek her bir sipariş için müşteri adı, ürün kategorisi ve toplam sipariş tutarını içeren tek bir analiz tablosu oluşturmak ve eksik verileri temizlemektir.
Pandas ile Zorluk: Üç farklı formattaki ve büyük hacimdeki dosyayı Pandas’a ayrı ayrı yüklemek ve sonra bunları birleştirmek (merge operasyonları), hem bellek hem de CPU açısından yoğun olacaktır. Özellikle JSON dosyasının ayrıştırılması ve ardından iki büyük DataFrame ile birleştirilmesi ciddi performans sorunları yaratabilir.
DuckDB ile Çözüm: DuckDB, farklı dosya formatlarını doğrudan sorgulama ve SQL’in güçlü JOIN yetenekleri sayesinde bu süreci basitleştirir ve hızlandırır.
import duckdb
import pandas as pd
import time
import os
import json
# Varsayımsal dosyaları oluşturma (Gerçek senaryoda bunlar mevcut olacaktır)
# Bu kısım sadece örnek veriyi oluşturmak içindir.
if not os.path.exists('musteri_bilgileri.csv'):
print("Örnek CSV oluşturuluyor...")
pd.DataFrame({
'musteri_id': range(1, 10_000_001),
'musteri_ad': [f'Musteri_{i}' for i in range(10_000_000)],
'adres': [f'Adres_{i}' for i in range(10_000_000)],
'kayit_tarihi': pd.to_datetime(pd.date_range('2020-01-01', periods=10_000_000, freq='D'))
}).to_csv('musteri_bilgileri.csv', index=False)
print("CSV oluşturuldu.")
if not os.path.exists('urun_katalogu.parquet'):
print("Örnek Parquet oluşturuluyor...")
pd.DataFrame({
'urun_id': range(1, 500_001),
'urun_ad': [f'Urun_{i}' for i in range(500_000)],
'kategori': [f'Kategori_{i % 100}' for i in range(500_000)],
'birim_fiyat': [round(i * 0.5 + 5, 2) for i in range(500_000)]
}).to_parquet('urun_katalogu.parquet', index=False)
print("Parquet oluşturuldu.")
if not os.path.exists('siparis_detaylari.json'):
print("Örnek JSON oluşturuluyor...")
orders = []
for i in range(20_000_000):
orders.append({
'siparis_id': i + 1,
'musteri_id': (i % 10_000_000) + 1,
'urun_id': (i % 500_000) + 1,
'miktar': (i % 10) + 1,
'siparis_tarihi': (pd.to_datetime('2023-01-01') + pd.Timedelta(days=i % 365)).strftime('%Y-%m-%d')
})
with open('siparis_detaylari.json', 'w') as f:
json.dump(orders, f)
print("JSON oluşturuldu.")
file_musteri = 'musteri_bilgileri.csv'
file_urun = 'urun_katalogu.parquet'
file_siparis = 'siparis_detaylari.json'
conn = duckdb.connect(database=':memory:', read_only=False)
start_time_duckdb_etl = time.time()
# Üç farklı dosyadan verileri birleştirme ve dönüştürme
etl_query = f"""
SELECT
s.siparis_id,
m.musteri_ad,
u.kategori AS urun_kategorisi,
s.miktar * u.birim_fiyat AS toplam_siparis_tutari,
s.siparis_tarihi
FROM '{file_siparis}' AS s
JOIN '{file_musteri}' AS m ON s.musteri_id = m.musteri_id
JOIN '{file_urun}' AS u ON s.urun_id = u.urun_id
WHERE s.miktar IS NOT NULL AND u.birim_fiyat IS NOT NULL
ORDER BY s.siparis_tarihi DESC
LIMIT 1000; -- Sadece ilk 1000 satırı gösterelim
"""
final_analysis_df = conn.execute(etl_query).fetchdf()
print(f"DuckDB ile ETL ve birleştirme süresi: {time.time() - start_time_duckdb_etl:.2f} saniye")
print("Birleştirilmiş ve Temizlenmiş Analiz Tablosu (İlk 5):")
print(final_analysis_df.head())
conn.close()
DuckDB, farklı formatlardaki dosyaları doğrudan okuyup karmaşık JOIN operasyonlarını bellekte veya diskte verimli bir şekilde yürütebilir. Bu, veri mühendislerinin ve analistlerin, veri entegrasyonu ve temizleme adımlarını çok daha hızlı tamamlamasına olanak tanır. Elde edilen Pandas DataFrame’i, daha sonra makine öğrenimi modelleri oluşturmak veya interaktif panolar hazırlamak için kullanılabilir.
Bu vaka analizleri, DuckDB’nin Pandas ile birlikte kullanıldığında büyük veri setlerinde ne kadar güçlü bir araç haline geldiğini açıkça göstermektedir. ETL süreçlerinden karmaşık analitik sorgulara kadar, DuckDB performansı artırırken iş akışını basitleştirir.
Performans Optimizasyonu ve İleri Düzey İpuçları: DuckDB’den En İyi Şekilde Yararlanmak
DuckDB, kutudan çıktığı haliyle bile etkileyici performans sunar. Ancak, büyük veri setleriyle çalışırken veya belirli performans hedeflerine ulaşmak istediğinizde, bazı optimizasyon tekniklerini ve ileri düzey ipuçlarını bilmek iş akışınızı daha da hızlandırabilir. Bu bölüm, DuckDB’den en iyi şekilde yararlanmanızı sağlayacak stratejileri ve ipuçlarını içermektedir.
Veri Formatları: Parquet ve Apache Arrow’un Gücü
DuckDB’nin performansını en üst düzeye çıkarmanın en önemli yollarından biri, verilerinizi doğru formatta depolamaktır. DuckDB, sütun tabanlı depolama için optimize edilmiştir ve bu nedenle Parquet ve Apache Arrow gibi sütun tabanlı formatlarla mükemmel bir uyum içindedir.
- Parquet: Sütun tabanlı, sıkıştırılmış ve optimize edilmiş bir dosya formatıdır. DuckDB, Parquet dosyalarını doğrudan sorgulayabilir ve yalnızca sorguda ihtiyaç duyulan sütunları okuyarak I/O maliyetini önemli ölçüde azaltır. Bu, özellikle geniş tablolarda (çok sayıda sütun) ve belirli sütunlara odaklanan analitik sorgularda performansı katlar.
- Apache Arrow: Bellek içi sütun tabanlı bir veri formatıdır. DuckDB ve Pandas (ve diğer birçok veri aracı) arasında veri aktarımı yaparken Arrow formatını kullanmak, veri kopyalama maliyetini azaltarak performansı artırır.
.fetch_arrow_table()metodu ile DuckDB sonuçlarını Arrow formatında alıp, oradan Pandas DataFrame’e dönüştürmek, büyük veri setlerinde daha hızlıdır.
Bellek Yönetimi ve Yapılandırma
DuckDB, akıllı bellek yönetimi sayesinde bellek dışı hatalarını nadiren verir. Ancak, daha iyi performans için bellek limitlerini ayarlayabilirsiniz. DuckDB, varsayılan olarak makinenizdeki RAM’in belirli bir yüzdesini kullanır. Bu limiti artırmak veya azaltmak mümkündür.
import duckdb
# DuckDB bağlantısı oluştururken bellek limitini ayarlama
# Örneğin, 4GB bellek kullanmasına izin verelim
conn = duckdb.connect(database=':memory:', read_only=False, config={'memory_limit': '4GB'})
# Mevcut bellek limitini kontrol etme
print(conn.execute("PRAGMA memory_limit;").fetchval())
# Veya sorgu içinde ayarlama
conn.execute("SET memory_limit='8GB';")
print(conn.execute("PRAGMA memory_limit;").fetchval())
# Geçici depolama dizini ayarlama (disk taşması için)
# Büyük veri setlerinde disk I/O performansını etkileyebilir
conn.execute("SET temp_directory='/tmp/duckdb_temp';") # Linux/macOS
# conn.execute("SET temp_directory='C:/temp/duckdb_temp';") # Windows
# Bağlantıyı kapatmayı unutmayın
conn.close()
Bellek limitini sisteminizdeki mevcut RAM’e göre ayarlamak, DuckDB’nin daha fazla veriyi bellekte tutmasına ve disk I/O’sunu azaltmasına yardımcı olabilir, bu da sorgu performansını artırır.
İndeksleme ve Optimizasyon
Geleneksel veritabanlarında indeksler, sorgu performansını artırmak için kritik öneme sahiptir. DuckDB, sütun tabanlı yapısı ve gelişmiş sorgu optimizasyon motoru sayesinde genellikle manuel indeksleme ihtiyacını azaltır. Ancak, belirli senaryolarda performansı daha da artırmak için bazı teknikler kullanılabilir:
- Sorted Tables: DuckDB, verileri belirli bir sütuna göre sıralanmış olarak depoladığında sorgu performansını artırabilir. Özellikle
ORDER BYveGROUP BYiçeren sorgularda bu faydalıdır. Parquet dosyalarını oluştururken verileri sıralı yazmak veya DuckDB’ye yükledikten sonra sıralı bir tablo olarak kaydetmek düşünebilirsiniz. - Statistics (İstatistikler): DuckDB, veriler hakkında istatistikler toplayarak sorgu planlayıcısını optimize eder. Bu genellikle otomatik olarak gerçekleşir, ancak nadiren de olsa manuel olarak istatistikleri güncellemek faydalı olabilir (büyük veri değişikliklerinden sonra).
Mobil Uyumlu HTML ve Raporlama İçin Sonuçların Görselleştirilmesi
DuckDB ve Pandas ile elde ettiğiniz analiz sonuçlarını genellikle bir web panosu veya raporlama aracı aracılığıyla sunmak istersiniz. Bu raporların mobil cihazlarda da düzgün görünmesi önemlidir. Doğrudan DuckDB veya Pandas çıktısı HTML değildir, ancak bu çıktıyı (örneğin, Pandas DataFrame’i) bir web uygulamasında kullanırken, responsive tasarım prensiplerini uygulayarak mobil uyumlu görünümler elde edebilirsiniz.
Örneğin, Pandas DataFrame’ini HTML’e dönüştürdükten sonra (df.to_html()), bu HTML’i içeren web sayfanızda CSS media query’leri kullanarak tabloların veya diğer elemanların mobil cihazlarda daha iyi görünmesini sağlayabilirsiniz:
<style>
/* Genel tablo stilizasyonu */
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 1em;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
/* Mobil cihazlar için responsive ayarlar */
@media screen and (max-width: 600px) {
table, thead, tbody, th, td, tr {
display: block;
}
thead tr {
position: absolute;
top: -9999px;
left: -9999px;
}
tr { border: 1px solid #ccc; }
td {
border: none;
border-bottom: 1px solid #eee;
position: relative;
padding-left: 50%;
text-align: right;
}
td:before {
position: absolute;
top: 6px;
left: 6px;
width: 45%;
padding-right: 10px;
white-space: nowrap;
text-align: left;
font-weight: bold;
}
/* Her sütun için etiket ekleme (veri-etiketi kullanarak) */
td:nth-of-type(1):before { content: "Sipariş ID"; }
td:nth-of-type(2):before { content: "Müşteri Adı"; }
td:nth-of-type(3):before { content: "Kategori"; }
td:nth-of-type(4):before { content: "Toplam Tutar"; }
td:nth-of-type(5):before { content: "Tarih"; }
}
</style>
Bu CSS kodu, ekran boyutu 600 pikselin altına düştüğünde tablonun her satırını dikey olarak düzenler ve her hücreye başlıklarını ekler. Bu, DuckDB ve Pandas ile elde ettiğiniz verilerin son kullanıcıya daha erişilebilir ve estetik bir şekilde sunulmasına yardımcı olur.
Bu ipuçları ve optimizasyon stratejileriyle, DuckDB’nin potansiyelini tam olarak kullanabilir ve büyük ölçekli veri analizi projelerinizde hem performansı hem de geliştirici deneyimini önemli ölçüde artırabilirsiniz.
Sonuç: Büyük Veri Analizinde Geleceğin İş Akışı
Bu makale boyunca, Pandas’ın büyük veri setleriyle çalışırken karşılaştığı zorlukları ve DuckDB’nin bu zorlukları nasıl aşarak Pandas’ı tamamladığını detaylı bir şekilde inceledik. Gördük ki, Pandas’ın sezgisel Python API’si ve veri keşfi için sunduğu kolaylık vazgeçilmezken, DuckDB’nin sütun tabanlı mimarisi, SQL desteği ve bellek/disk yönetimi, büyük ölçekli analitik sorgularda ve ETL süreçlerinde eşsiz bir performans sunuyor.
DuckDB’nin doğrudan dosya sisteminden (CSV, Parquet, JSON) sorgulama yeteneği, Pandas DataFrameleri ile sorunsuz entegrasyonu ve optimize edilmiş SQL motoru, veri bilimcilerine ve mühendislerine daha önce mümkün olmayan bir esneklik ve hız sağlıyor. Artık, gigabaytlarca hatta terabaytlarca veriyi, dağıtık sistemlerin karmaşıklığına girmeden, tek bir makinede bile verimli bir şekilde işleyebiliriz.
Geleceğin veri analizi iş akışı, bu iki güçlü aracın sinerjisine dayanacak gibi görünüyor: Veri keşfi, ön işleme ve küçük ölçekli manipülasyonlar için Pandas’ın gücünden yararlanırken, performans kritik gruplamalar, birleştirmeler ve karmaşık SQL sorguları için DuckDB’ye başvurmak. Bu hibrit yaklaşım, hem geliştirme hızını hem de analizlerin ölçeklenebilirliğini artırarak veri odaklı kararlar almayı kolaylaştıracaktır. DuckDB ve Pandas, büyük veri dünyasında yan yana yürüyerek, analistlerin ve veri bilimcilerin ellerindeki en değerli araçlardan biri haline geliyor.
Sıkça Sorulan Sorular
DuckDB tamamen Pandas’ın yerini mi alacak?
Hayır, DuckDB’nin amacı Pandas’ın yerini almak değil, onu tamamlamaktır. Pandas, hala veri keşfi, hızlı prototipleme, küçük ve orta ölçekli veri manipülasyonları için mükemmel bir araçtır. DuckDB ise Pandas’ın bellek dışı kalma veya yavaşlama eğiliminde olduğu büyük ölçekli analitik sorgular ve ETL süreçleri için devreye girer. İkisi birlikte en güçlü iş akışını sunar.
DuckDB kullanmak için SQL bilmek şart mı?
DuckDB’nin tüm gücünden yararlanmak için SQL bilgisi kesinlikle faydalıdır, çünkü DuckDB bir SQL veritabanıdır. Ancak, temel SQL komutları (SELECT, FROM, WHERE, GROUP BY, JOIN) ile başlayabilir ve zamanla daha karmaşık sorgulara geçebilirsiniz. Python API’si aracılığıyla Pandas DataFramelerinizle etkileşim kurarken bile SQL’in gücünden faydalanabilirsiniz.
DuckDB büyük veri kümelerini belleğe mi yükler?
DuckDB, öncelikle belleği kullanmaya çalışır (bellek içi veritabanı olarak da çalışabilir). Ancak, veri seti makinenizin RAM’ini aştığında, akıllıca disk tabanlı bir yaklaşıma geçer ve verileri diske taşır. Bu sayede, Pandas’ta sıkça görülen “MemoryError” hatalarını önlerken, büyük veri setleriyle bile sorunsuz bir şekilde çalışabilir.
DuckDB’nin diğer yerleşik veritabanlarından (örneğin SQLite) farkı nedir?
DuckDB, SQLite gibi gömülü bir veritabanı olmasına rağmen, temel farkı kullanım amacıdır. SQLite OLTP (işlem odaklı) iş yükleri için tasarlanmışken, DuckDB OLAP (analitik) iş yükleri için özel olarak optimize edilmiştir. DuckDB’nin sütun tabanlı depolama, gelişmiş sorgu optimizasyonu ve analitik fonksiyonlara odaklanması, onu büyük ölçekli veri analizi için çok daha hızlı ve verimli kılar.
DuckDB ve Spark arasındaki fark nedir?
Spark, dağıtık bir işlem çerçevesidir ve birden fazla makine (küme) üzerinde büyük veri setlerini işlemek için tasarlanmıştır. DuckDB ise tek bir makinede (laptop, sunucu) çalışmak üzere tasarlanmış, performansı yüksek bir OLAP veritabanıdır. Eğer verileriniz tek bir makinenin depolama ve bellek kapasitesine sığıyorsa, DuckDB Spark’a göre çok daha basit kurulum, yönetim ve genellikle daha düşük gecikme süresi sunar. Veri hacmi tek makineyi aştığında Spark gibi dağıtık çözümler devreye girer. DuckDB “tek makinedeki Spark” olarak düşünülebilir.
