Microsoft JDBC Driver: ResultSet ve Bulk Copy Optimizasyonu
Veritabanı sürücüsü, uygulamanın yürütme yolunun tam ortasında oturur. Sık çalışan bir kod yolundaki gereksiz iş tek başına küçük görünür, milyonlarca işlem boyunca birikince görünür bir maliyete dönüşür. Microsoft son birkaç sürümde Microsoft JDBC Driver for SQL Server içindeki sıcak yolları tek tek profilleyip uygulama davranışını değiştirmeden verimliliği artırmaya odaklandı. Aşağıda ResultSet işleme, bellek ayırma, bulk copy, parametre metadata’sı, Always Encrypted ve kimlik doğrulama tarafında yapılan iyileştirmeleri, her birinin uygulama geliştiricisine ne kazandırdığıyla birlikte özetliyorum.
Çalışmanın tamamı tek bir ilkeyi izliyor: maliyetin nerede olduğunu ölç, neden orada olduğunu anla, doğruluğu ve geriye dönük uyumluluğu bozmadan gereksiz işi kaldır.
ResultSet işlemede kısaltılan sıcak yollar
İnceleme, farklı SQL Server veri tiplerini bir arada barındıran büyük ve seyrek (sparse) sonuç kümeleri döndüren müşteri iş yükleriyle başlamış. Profil çıktıları darboğazın çoğu zaman ağ G/Ç olmadığına işaret ediyor; maliyet, TDS akışından değer üretilirken oluşan bellek ayırmalarından, geçici nesnelerden ve tekrarlanan işlerden geliyor.
Sürücü lazy decoding modelini kullanıyor, yani değerler uygulama getter metotlarıyla isteyene kadar wire (hat) temsilinde kalıyor. Adaptive buffering, streaming erişim, Always Encrypted, sunucu imleçleri ve güncellenebilir sonuç kümeleri bu model sayesinde mümkün. Ekip de mimariyi yeniden tasarlamak yerine mevcut sıcak yolları kısaltmayı, istenen değeri üretmek için gerekli olmayan işi elemeyi tercih etmiş.
Erken NULL tespiti
SQL Server, NULL bilgisini NBCROW bit haritası üzerinden değer materyalizasyonu başlamadan önce veriyor. NULL kontrolü yolun daha erken bir noktasına taşındı; NULL olduğu bilinen bir değer artık decode mekanizması başlatılmadan, sonucu zaten bilinen bir yük işlenmeden dönebiliyor. Seyrek sonuç kümelerinde bu, NULL sütunlar boyunca tekrarlanan çözümleme işini ortadan kaldırıyor.
Daha düşük allocation baskısı
Profilleme, ResultSet gezinirken kısa ömürlü decoder nesnelerinin tekrar tekrar oluşturulduğunu gösterdi. Decoder durumunun güvenle yeniden kullanılabildiği yerlerde her değer için yeni nesne üretilmiyor artık. Geçici bellek ayırmaları ve bunlara bağlı çöp toplama yükü, mevcut çözümleme davranışı korunarak azalıyor.
Sayısal ve tarih/saat değerlerinde primitive öncelikli yol
Yaygın sayısal değerler, MONEY ve temporal tipler, son JDBC biçimine ulaşmadan önce ara temsillerden geçebiliyordu. Güncellenen uygulamada yaygın değerler için daha doğrudan, primitive öncelikli bir yol kullanılıyor, keyfi hassasiyet (arbitrary precision) gerektiren değerler içinse mevcut yollar duruyor. Böylece TDS temsilinden uygulamaya dönen değere giden yol kısalıyor.
Sadeleşen string okuma
Sıradan karakter değerlerinin, büyük streaming değerlerle aynı işleme yolunu kullanması gerekmiyor. Yaygın getString() yolu yeniden kullanılabilir tamponlar ve daha doğrudan değer oluşturmayla sadeleştirildi; büyük nesneler, streaming erişim ve adaptive buffering için mevcut davranış aynen korundu.
İnceltilmiş sıcak yollar
Paket sınırı yönetimi, satır durumu ilklendirme ve tanılama günlüğü kontrolleri gibi tek başına ucuz ama çok sık çalışan işlemlerde de gereksiz iş kaldırıldı. Tek tek küçük kazanımlar bunlar, frekansları yüzünden toplamda anlamlı hale geliyor.
Bulk copy tarafında daha fazla denetim
Müşteri iş yükleri ve topluluk katkıları, bulk copy tabanlı toplu insert’lerde benzer fırsatlara işaret etti. Buradaki hedef dönüşüm maliyetini azaltmakla sınırlı değildi; uygulamalara bulk yürütme üzerinde daha fazla denetim vermek, uygun işlemleri bulk copy yolunda tutmak ve değerler SQL Server’a ulaşmadan önce gereksiz dönüşümleri engellemek de hedefler arasındaydı.
Sürücü, uygun toplu insert’leri useBulkCopyForBatchInsert=true ile SQL Server bulk copy üzerinden yönlendirmeyi zaten destekliyordu. Bu yetenek, ilgili Bulk Copy API seçeneklerini açığa çıkaran bağlantı özellikleriyle genişletildi. Uygulamalar standart PreparedStatement programlama modelini kullanmaya devam ederken kısıt denetimi, tetikleyiciler, identity ve NULL davranışı, tablo kilitleme, şifreli değer değişiklikleri ve batch boyutu gibi davranışları kontrol edebiliyor:
bulkCopyForBatchInsertAllowEncryptedValueModifications=true
bulkCopyForBatchInsertCheckConstraints=true
bulkCopyForBatchInsertFireTriggers=true
bulkCopyForBatchInsertKeepIdentity=true
bulkCopyForBatchInsertKeepNulls=true
bulkCopyForBatchInsertTableLock=true
bulkCopyForBatchInsertBatchSize=<application-defined size>
Uygun işlemleri bulk yolunda tutmak: Aslında uygun olan bazı toplu insert’lerin satır satır yürütmeye düştüğü durumlar tespit edildi. Özellikle MONEY ve temporal SQL tiplerini içeren ifadeler, bu değerler bulk copy tarafından işlenebilecekken bile bulk yolundan çıkabiliyordu. Bulk copy dönüşüm katmanı bu tipleri doğrudan işleyecek şekilde güncellendi, desteklenen daha fazla işlem artık yüksek verimli yolda kalıyor.
String temsilinin korunması: Topluluk bildirimleri, sendStringParametersAsUnicode=false kullanıldığında gereksiz dönüşümler ve aksanlı karakterlerde kodlama sorunları olduğunu gösterdi. Yeni uygulamada değerler hedef kodlama aşamasına kadar string temsilinde tutuluyor, böylece gereksiz dönüşümler ortadan kalkarken beklenen kodlama davranışı da korunuyor.
Spark iş yükleri için not: Yüksek hacimli veri aktarımına odaklanan uygulamalar, ağ transfer yükünü azaltmak için JDBC packetSize değerini 32767‘ye çıkarmayı değerlendirebilir. Kaynak, bu ayarın etkisinin ağ koşullarına, batch boyutuna, partition yapısına ve dağıtım ortamına bağlı olduğunu, dolayısıyla temsili iş yükleriyle doğrulanması gerektiğini vurguluyor.
Parametre metadata’sını açıkça bildirmek
Parametre metadata’sı, SQL Server tarafındaki sorgu optimizasyonunu etkileyebiliyor. Uygulama parametre boyut bilgisini vermediğinde sürücü, gerçek veri modelinden daha geniş parametre bildirimleri üretebiliyor, bu da plan seçimine ve yürütme verimliliğine yansıyabiliyor.
Uygulamalar beklenen metadata’yı defineParameterType() ile veya uzunluk bilgisi alan setObject() aşırı yüklemesiyle iletebilir. İki API de ek metadata gidiş-dönüşü gerektirmeden alana özgü boyut bilgisini aktarmayı sağlıyor.
pstmt.defineParameterType(parameterIndex, Types.VARCHAR, expectedLength);
pstmt.setString(parameterIndex, value);
pstmt.setObject(parameterIndex, value, Types.VARCHAR, expectedLength);
defineParameterType(), SQL tipini ve beklenen uzunluğu prepared statement parametresiyle ilişkilendirir; bu metadata sonraki yürütmelerde ve batch işlemlerinde yeniden kullanılabilir. setObject() içindeki scaleOrLength argümanı ise beklenen uzunluk ipucunu değerin bağlandığı noktada verir. Karakter ve ikili parametrelerde bu ipucu değerin kendisini sınırlamaz, üretilen parametre bildirimini etkiler. Metadata sürücünün mevcut Always Encrypted gereksinimleriyle de uyumlu kalıyor.
Always Encrypted ve kimlik doğrulamada azalan tekrar iş
Topluluk kaynaklı bir inceleme, enclave destekli Always Encrypted senaryolarında anahtar sağlayıcı işinin tekrarlandığını ortaya çıkardı. Profilleme, enclave olmayan şifreli işlemlerin aksine enclave destekli yolların, yeniden kullanılabilir anahtar materyali mevcutken bile ek sağlayıcı aramaları yapabildiğini gösterdi. Mevcut simetrik anahtar önbelleği altyapısı enclave destekli anahtar alımını da kapsayacak şekilde genişletildi; uygun anahtar materyali önbellekteyse sürücü sağlayıcı aramasını tekrarlamak yerine onu yeniden kullanıyor. Mevcut önbellek semantiği ve güvenlik sınırları korunuyor.
Yüksek eşzamanlılıktaki iş yüklerinin profillemesinde ise service principal token alımı sırasında çekişme (contention) tespit edildi: yalnızca geçerli bir önbellekli token’a ihtiyaç duyan istekler bile token yenileme senkronizasyonuna takılabiliyordu. Kaynağa göre yaklaşan bir sürüm, yenileme senkronizasyonuna girmeden önce token önbelleğini kontrol ederek bu yolu optimize edecek, ayrıca yenileme koordinasyonunun kapsamı daraltılarak ilgisiz kimlik doğrulama işlemlerinin birbirini bloklama olasılığı azaltılacak. Mevcut token alma ve yenileme semantiği korunacak.
Ortak mühendislik deseni
Bütün bu iyileştirmeler aynı deseni izliyor: gerçek iş yüklerini profille, gereksiz işin nerede oluştuğunu bul ve uygulamaya görünen davranışı değiştirmeden kaldır. Decoder başlatılmadan NULL tespiti, gereksiz ara temsillerin atlanması, uygun işlemlerin bulk copy yolunda tutulması, önbellekteki anahtar materyalinin yeniden kullanılması, geçerli token varken senkronizasyondan kaçınılması. Hepsi aynı yaklaşımın farklı katmanlardaki yansıması.
Buradan çıkan genel ders, sürücü performansının her zaman yeni bir algoritma ya da mimari yeniden tasarım gerektirmediği. Mevcut yürütme yollarını, her yolun yalnızca doğru sonucu üretmek için gereken işi yaptığından emin olacak kadar derinlemesine anlamak da ciddi kazanımlar getirebiliyor.
Sürüm ve katkı
Microsoft JDBC Driver for SQL Server’ın güncel sürümü Maven Central üzerinden com.microsoft.sqlserver:mssql-jdbc koordinatıyla alınabiliyor. İş yüküne özgü yapılandırma seçenekleri için sürücü dokümantasyonu inceleniyor, yeniden üretilebilir sorunlar ve performans bulguları GitHub deposu üzerinden bildirilebiliyor. Microsoft, memory-segment API’leri ve ek bulk copy iyileştirmeleri dahil olmak üzere çalışmanın süreceğini belirtiyor.
Kaynaklar ve İleri Okuma
- Faster by Design: Performance engineering in the Microsoft JDBC Driver for SQL Server (Ananya Garg, Microsoft for Java Developers)
- Using bulk copy API for batch insert operation — uygunluk koşulları, bilinen kısıtlar ve desteklenen veri tipleri
- setObject (SQLServerPreparedStatement) API referansı
- microsoft/mssql-jdbc GitHub deposu
- ResultSet iyileştirmeleri: PR #2600 — NULL değerlerde erken dönüş, PR #2974 — okuma yolu optimizasyonları, PR #2975 — decimal ve numeric decoder, PR #2991 — ek decoder ve buffer optimizasyonları, PR #2955 — ince taneli loglama
- Bulk copy: PR #2555 — bulk copy batch özelliklerinin açılması, PR #2670 — desteklenen değerleri bulk yolunda tutma, PR #2735 — string temsilinin korunması
- Parametre metadata’sı: PR #2960 — defineParameterType() desteği (kaynakta ayrıca setObject uzunluk ipucu için PR #3026, Always Encrypted için PR #2964, kimlik doğrulama için PR #2982 ve PR #2983 listeleniyor)







Yorum gönder