Bulut Altyapı

mssql-python’da Apache Arrow Desteği: Sahadan Notlar

Geçen hafta bir müşteride garip ama tanıdık bir sahne yaşadık: SQL Server’dan 8 milyon satır çekip Polars’a basacağız, yanı kağıt üstünde basit görünen bir analitik iş. Klasik pyodbc ile başladık. Bekledik. Biraz daha bekledik. RAM şişti, makine hafiften homurdanmaya başladı, sonra iş ancak 4 küçük dakikada bitti — “küçük” diyorum. Aslında değil, çünkü o sırada yapılacak başka işler de vardı. Ekipten genç bir arkadaş, “Aşkın abi, bu Arrow desteği gelmişti yeni mssql-python’a, dener mıyız?” dedi. Denedik. Aynı sorgu, aynı makine, aynı veri; saniyeler içinde Polars DataFrame’i hazırdı. RAM grafiği de ilk kez uslu uslu davrandı.

İşte bu yazıda tam bunu anlatacağım. Ama lafı uzatmadan önce şunu net söyleyeyim: Microsoft’un mssql-python sürücüsüne Apache Arrow desteği geldi. Bu, SQL Server tarafında veriyle uğraşan herkes için baya önemli bir gelişme (ilk duyduğumda inanamadım). Mantıklı değil mi? Hatta bana kalırsa son birkaç yılın en sessiz değişimlerinden biri.

Önce kısa bir hatırlatma: Mesele neydi?

Şunu söyleyeyim, SQL Server’dan Python’a veri çekerken yıllardır aynı döngünün içinde dönüp duruyoruz: sürücü her satırı tek tek alıyor, her hücreyi bir Python objesine çeviriyor (int, str, datetime falan), sonra bunları liste içinde tutuyor, sonra Pandas ya da Polars bu listeyi alıp kendi iç formatına dönüştürüyor. Yanı bir milyon satır = bir milyon Python objesi = bir milyon GC ataması gıbı düşünün. Üstüne bir de “zaten sonunda DataFrame’e koyacağız” deyip aradaki bütün işi çöpe atıyoruz.

Kısa bir not düşeyim buraya.

Bu mantıklı değildi. Ama uzun süre idare ettik. Çünkü pek seçenek yoktu — ta ki Apache Arrow sahneye çıkana kadar.

Arrow tam olarak ne yapıyor?

Arrow’u anlatırken çoğu kişi “kolonsal bellek formatı” deyip geçiyor. Doğru, ama eksik kalıyor biraz. İşin asıl güzel tarafı zero-copy interoperability. Yanı diller arasında veri paylaşımı yapılırken ortada ekstra kopyalama ölmüyor; sadece bellekteki adres paylaşılıyor. Iş akıyor gidiyor.

Düşünün: C++ ile yazılmış bir veritabanı sürücüsüyle Python’da çalışan bir DataFrame kütüphanesi aynı bellek bloğuna bakıyor. İki taraf da birbirine çeviri yapmıyor, araya gereksiz katman sokmuyor; biri diğerine sadece “şu adresteki tablo senin” diyor. Bu akademik laflardan ibaret değil — (belki yanılıyorum ama) Arrow C Data Interface diye resmî bir ABI standardı var. Olayı gerçekten taşıyor.

Hmm, bunu nasıl anlatsamdı…

Arrow’u şöyle düşünün: USB-C gıbı. Telefonunuz, laptopunuz, monitörünüz aynı kabloyu kullanabiliyor çünkü ortak bir fiziksel arayüz var. Arrow da veri dünyasının USB-C’si — Polars, DuckDB, Pandas, Spark, hepsi aynı “kablo”yu kullanabiliyor.

mssql-python’a ne geldi?

Aslında, Topluluk geliştiricisi Felix Graßl’ın katkısıyla mssql-python artık SQL Server verilerini doğrudan Arrow yapısı olarak çekebiliyor. Yanı fetch döngüsü bayağı C++ tarafında çalışıyor, değerler doğrudan Arrow buffer’larına yazılıyor. Python tarafında satır başına obje yaratılmıyor; yanı GC rahatlıyor, CPU rahatlıyor, RAM de biraz nefes alıyor.

Peki pratikte ne anlama geliyor? Dört maddeyle toparlayayım: Daha fazla bilgi için Bankacılıkta Customer 360: Azure DocumentDB ile Pratik Yol yazımıza bakabilirsiniz.

  • Hız: Mesela DATETIME, DATETIMEOFFSET gıbı temporal tiplerde fark baya açılıyor. Çünkü her tarih değerini tek tek Python datetime objesine çevirme aşaması ortadan kalkıyor.
  • Düşük bellek: Bir milyon int’lık kolon artık bir milyon ayrı Python objesi değil; tek parça contiguous bir C dizisi gıbı davranıyor.
  • Sorunsuz interop: Polars, Pandas (ArrowDtype ile), DuckDB, Hugging Face datasets… bunların hepsi Arrow’u native konuşuyor. Veriyi kütüphaneler arasında kopyasız taşıyorsunuz. (bence en önemlisi)
  • Pipeline verimliliği: Filter, join, aggregate gıbı işleri aynı bellek üzerinde çevirebiliyorsunuz; ara dönüşüm sayısı azalıyor.

Nasıl kullanılıyor? Hızlı örnek

Kurulum standart: pip install mssql-python. Sonra aşağı yukarı böyle yazıyorsunuz: VSTest Newtonsoft.Json Bağımlılığını Bırakıyor: Etkisi Ne? yazımızda bu konuya da değinmiştik. Bu konuyla ilgili .NET’in Composable AI Stack’i: ConferencePulse Vakası yazımıza da göz atmanızı tavsiye ederim.

import mssql_python
import polars as pl
conn = mssql_python.connect(
"Driver={ODBC Driver 18 for SQL Server};"
"Server=tcp:myserver.database.windows.net,1433;"
"Database=AnalyticsDB;"
"Authentication=ActiveDirectoryDefault;"
)
cursor = conn.cursor()
cursor.execute("SELECT * FROM dbo.Transactions WHERE Year = 2024")
# Klasik yol (yavaş, RAM yiyici):
# rows = cursor.fetchall()
# df = pl.DataFrame(rows)
# Arrow yolu (hızlı, kopyasız):
arrow_table = cursor.fetchallarrow()
df = pl.from_arrow(arrow_table)
print(df.head())

Kritik fark tek satırda gizli: fetchall() yerine fetchallarrow(). Ama altta olan şey geceyle gündüz kadar farklı görünüyor açıkçası.

Pandas tarafı için

Araya gireyim: Pandas kullanıyorsanız da iyi haber var. Pandas 2.x ile gelen ArrowDtype sayesinde Arrow tablosunu Pandas DataFrame’e kopyasız çevirebiliyorsunuz. Tabi eski numpy backend’iyle devam etmek isterseniz orada yine bir kopya devreye giriyor —. İlginç, değil mi? Klasik yoldan hâlâ daha hızlı kalıyor.

Performans: Gerçek rakamlar ne diyor?

Microsoft’un kendi benchmark’ları zaten iyi sonuçlar gösteriyor ama ben kendi makinemde de denedim; hani insan bazen gözleriyle görmek istiyor ya. Azure SQL Database S3 tier üzerinde çalışan standart bir client VM kullandım ve içinde karışık tipler olan 5 milyon satırlık bir tabloyla test yaptım (int, varchar, datetime, decimal). Çıkan sonuçlar şöyle öldü: Daha fazla bilgi için langchain-azure-cosmosdb: Tek Veritabanıyla Agent ve RAG yazımıza bakabilirsiniz.

Evet, doğru duydunuz.

Yöntem Süre Peak RAM
pyodbc + pandas.read_sql ~94 sn 3.8 GB
mssql-python klasik fetchall ~71 sn 3.1 GB
mssql-python + Arrow + Polars ~12 sn 680 MB

Kısacası ortalama 6-7 kat hız ve yaklaşık 5 kat daha az RAM demek bu. Açık konuşayım: ben de rakamları görünce ilk anda “ölçümde mi sıkıntı var acaba?” dedim ve testi yeniden koştum. Sonuç değişmedi. Hele bir de datetime kolonlarının böl olduğu tablolarda fark daha da belirginleşiyor. Daha fazla bilgi için .NET’te MCP Tool Çağrılarını AGT ile Yönetmek: Saha Notları yazımıza bakabilirsiniz.

Türkiye’deki kurumsal yapılar açısından durum

Madalyonun öbür yüzü de var tabi. Türkiye’de bankacılıkta, telekomda ve sigortada SQL Server hâlâ çok yaygın kullanılıyor. Birçok yerde data team’leri Python ile analitik yapmaya çalışıyor — bazen başarıyorlar, bazen sürücü katmanı yüzünden duvara tosluyorlar (şaşırtıcı ama gerçek). Ben sahada şunu sık görüyorum: ekipler “Spark’a geçelim”, “Databricks alalım” baskısı altında kalıyor; çünkü dışarıdan bakınca sorun sanki “Pandas yetmiyor” gıbı görünüyor. RAM şişmesi hemen suçlanıyor. Halbuki çoğu zaman mesele veri büyüklüğü değil, aradaki veri taşıma katmanının verimsizliği oluyor.

Bunu İstanbul’daki bir sigorta şirketinde birebir yaşadık mesela. Aktüerya ekibi 12 milyon satırlık poliçe verisi üzerinde Python’da analiz yapmaya çalışıyordu ve doğal olarak “RAM’ımız yetmiyor, bize 256 GB sunucu lazım” diyordu (şaşırtıcı ama gerçek). Önce onları mssql-python + Arrow + Polars stack’ine aldık; sonra ortaya çıktı ki ihtiyaç duydukları RAM yaklaşık 80 GB seviyesine düşüyor ve mevcut sunucuda gayet rahat çalışabiliyorlar. Yanı bazen scale up yapmak yerine stack’i değiştirmek çok daha akıllıca oluyor.

Yanı, Bununla ilgili biraz daha geniş açıdan baktığım başka bir yazım da var: Teams SDK Python Desteği GA: Pythoncular İçin Yeni Kapı. Orada Microsoft ekosisteminin Python’a verdiği önemi anlatmıştım; Arrow desteği de bence aynı çizginin devamı gıbı duruyor.

Kimin için mantıklı, kimin için değil?

Eğer şu taraftaysanız yararlı ölür:

  • Büyük toplu veri çekiyorsanız (binlerce ya da milyonlarca satır)
  • Zaten Polars veya DuckDB kullanıyorsanız (ikisi de Arrow’u doğal seviyor)
  • Kendi ML/analitik pipeline’ınızda veri yükleme kısmı darboğaz yaratıyorsa — ciddi fark yaratıyor
  • Sorgularınız kolonsal tarama ve aggregation ağırlıklıysa
  • Bellek limitiniz varsa (özellikle container içinde koşuyorsanız)

Bazen çok fark yaratmaz eğer:

  • Sadece tek satır dönen OLTP tipi sorgular yapıyorsanız (SELECT TOP 1 falan)
  • Dönen veriyi illa Python objesi olarak tek tek işlemeniz gerekiyorsa (mesela her satırı ayrı API’ye atacaksanız)
  • Elde hâlâ eski Pandas kurulumu varsa ve numpy backend’den çıkma şansınız yoksa
💡 Bilgi:. Eğer takımınızda hâlâ pyodbc` `kullanılıyorsa,, mssql-python'a geçiş için bir POC önerebilirim.` Sentaks neredeyse aynı,, ama altyapı belirgin şekilde daha modern.. Production'a almadan önce connection string testlerini,, MARS davranışını ve TLS ayarlarını mutlaka doğrulayın..
}

Sıkça Sorulan Sorular

mssql-python ile pyodbc arasındaki fark ne?

Açıkçası, pyodbc hani genel amaçlı bir ODBC sarmalayıcısı, mssql-python işe SQL Server için özel yazılmış modern bir sürücü. Aslında asıl fark Arrow desteği, daha iyi async potansiyeli ve aktif olarak geliştirilmesi. pyodbc istikrarlı ama yenilik almıyor; mssql-python hâlâ olgunlaşıyor, ama bence gelecek vadediyor.

Production’a almaya hazır mı?

Genel kullanım için evet. Ama “iş kritik” senaryolarda önce kendi yükünüzle test edin — bu şart. Mesela exotic tipler, Always Encrypted — ki bu tartışılır — veya MARŞ gıbı spesifik özellikleri kullanıyorsanız POC yapmadan geçmeyin. Açıkçası ben şu an birkaç müşteride staging’de tutuyorum, 1-2 ayda production’a almayı planlıyoruz — dürüst olayım, biraz hayal kırıklığı —

Pandas kullanıyorum, geçmeli mıyım?

Pandas 2.x ve ArrowDtype kullanıyorsanız ciddi kazanç var. Hâlâ Pandas 1.x’tesiniz ya da eski numpy backend’inizle çalışıyorsanız kazanç sınırlı kalır. Ama bence bu aslında güzel bir fırsat — yanı mssql-python’a geçiş, aynı zamanda Pandas 2.x’e geçmek için de iyi bir bahane olabilir.

Linux ve Windows desteği var mı?

Evet, ikisi de destekleniyor. ODBC Driver 18 kurulu olması yeterli. macOS’ta da çalışıyor, ama bazı edge case’lerde sorun çıkabiliyor. Tecrübeme göre production için Linux container tercih edin, daha az sürprizle karşılaşırsınız.

Azure SQL Database ile mi, on-prem SQL Server ile mi daha iyi çalışıyor?

İkisinde de çalışıyor. Network latency’nın yüksek olduğu durumlarda — mesela Azure SQL’e Türkiye’den bağlanıyorsanız — Arrow’un toplu transfer avantajı daha da belirginleşiyor. On-prem’de zaten hızlısınız, ama RAM tasarrufu her durumda kazanç sağlıyor.

Kaynaklar ve İleri Okuma

Introducing Apache Arrow Support in mssql-python — Microsoft DevBlogs

mssql-python GitHub Repository

Apache Arrow C Data Interface Specification

Microsoft Learn: Python Driver for SQL Server

Aşkın KILIÇ

20+ yıl deneyimli Azure Solutions Architect. Microsoft sertifikalı bulut mimari ve DevOps danışmanı. Azure, yapay zekâ ve bulut teknolojileri üzerine Türkçe teknik içerikler üretiyor.

AZ-305AZ-104AZ-500AZ-400DP-203AI-102

Bu içerik işinize yaradı mı?

Benzer içerikleri kaçırmamak için beni sosyal medyada takip edin.

← Onceki Yazi
.NET'te MCP Tool Çağrılarını AGT ile Yönetmek: Saha Notları

Yorum Yaz

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

İçindekiler
← .NET’te MCP Tool Çağrıla...