BulkInsert ile Hızlı Veri Aktarımı

Giriş

Günümüz uygulamalarının, en büyük gereksinimi hızlı veri yükleme olayıdır. Geçmişten günümüze gelen bu gereksinim 2000 li yıllardan itibarenBüyük Veri(BigData) ve Veri İşleme(DataProcessing) kavramları ile önemini bir kez daha ortaya koymuştur. It sektörünün bu alanda önemli bir sorunu ise var olan datayı hızlıca veritabanına aktarmaktır. Bu alanda, It sektöründe populer olan iki Database Yönetim Sistemi göze çarpmaktadır.
Reletional Database Management System(RDMS) ve Non- Reletional Database Management System (N-RDMS) olarak adlandırılan bu yöntemler depolama, ölçeklendirme ve maliyet yönlerinden farklılık gösterir.

Bu araştırmada RDMS sistemler aracılığı ile büyük miktarda veri aktarımını üzerine çalışılmıştır.

RDMS Nedir?

Temel olarak RDMS, verilerin tablo şeklinde saklanması olarak düşünülebilir. 1970 li yıllarda kullanılmaya başlanan bu model günümüzde tercih edilen modellerdendir. Tablolarda saklanan veriler satır –sütun mantığına göre depolanır. RDMS sistemi matematiksel bağlantılar temel alınarak geliştirilmiştir. Kısıtlayıcılar (pk, fk,constraint, uq) ve Programatik Çözümler(Stoder Procedure, View, Trigger) ile veri yönetimi gerçekleştirilir.

* Bu kısımdan sonra gösterilecek kod parçacıklarında C#, T-Sql, Entiti-Freamwork, Ado.Net deki yapılar temel alınarak anlatılacaktır.

RDMS de Veri Aktarımı

Bu veri aktarımını bir örnek üzerinden inceleyelim. Örneğimizde,C# scriptleri ile Ado.Net üzerinden MS-SQL veritabanına RDMS yöntemi ile veri aktarımı gerçekleştirilecektir.

alt

Ado.Net aracılığı ile oluşturulmuş olan T-Sql raw query sinin aşağıdaki şekilde oluştuğunu varsayalım (4 tane kayıt ekli oldğunu kabul ediyoruz.)

INSERT INTO MyTable (id, name) VALUES (1,’isim1’)
INSERT INTO MyTable (id, name) VALUES (2,’isim2’)
INSERT INTO MyTable (id, name) VALUES (3,’isim3’)
INSERT INTO MyTable (id, name) VALUES (4,’isim4’)

Oluşan T-Sql çıktısına göre, MS-Sql kanadında; her bir Insert Query si için şu adımlar gerçekleşecektir.

Yeni gelen datarow u oku. (I/O) progress

Kısıtlayıcıları kontrol et

Veriyi kaydet

Veri tutarlılığını kontrol et.

Sıradaki işleme geç (I/O) progress

Yukarıdaki bilgiler ışığında, bu yöntemin en iyi kayıt ekleme yöntemi olduğu düşünülebilir. Kayıt sayısı çok büyük olmayan kayıtlar için bu gerçektende söylenebilir. Fakat, 1.000.000 tane kaydı bu şekilde sisteme eklemek istediğimizi düşünelim. 1.000.000 kez yukarıdaki sürecin tekrarlanması gerekecektir. Buda bellek kullanımı, veri hattı kullanımı açısından ciddi bir maliyet demektir. Verinin, databse e yüksenme süreci ise saatler alabilir.

BulkInsert İle Hızlı Veri Aktarımı

1.000.000 veriyi az maliyet ile saniyeler içinde aktarabilir miyiz? Günümüz Database teknolojilerinde bu mümkündür. “BulkKing” veya “BulkInsert” olarak adlandırılan bir yaklaşım bize az maliyet ve zamanlama açısından büyük avantajlar sağlamaktadır.

BulkInsert Çalışma Mekanizması

Temel olarak BulkInsert, SqlServer veritabanı altyapısı ile entegre olarak çalışır. Geleneksel kayıt ekleme mekanizmaları row bazlı olarak çalışırlar ve transiction logları bu yapıya göre oluşur. BulkInsert yaklaşımında ise PageLevel bazlı olarak bir çalışma gerçekleşir. Transiction logları PageLevel mantığına göre yazılır.

Örnek Uygulama

Aşağıda yer alan kod parçacıklarında C#,Ado.Net, EntityFreamwork, .Net Freamwork den alıntılar yapılmıştır.

BulkInsert mekanizması aracılığı ile veritabanına aktarım gerçekleştirmek istediğimizde, SqlBulkCopyColumnMapping yaklaşımı kullanılabilir.
SqlBulkCopyColumnMapping nin temel amacı, SQL server tablolarına, başka bir dataSource dan veri aktarımı gerçekleştirmektir. Bu aktarım sırasında, BulkInsert altyapısı kullanılır.

SqlBulkCopy yöntemi ile veri ekleme işlemi yapılmak istenirse, ilgili verilerin DataTable formatına uygun olarak sisteme yüklenmesi gerekir.

alt

Member Poco class ı base olarak List customerList de var olan 1.000.000 kaydı database de yer alan “Member” tablosuna ekleyelim.

alt

Bazı Kavramların Açıklamaları

Connection: Database bağlantı yolunu gösterir.

tableName: Ms-Sql server da ilgili kayıtları ekleneceği tablo adı

IList list: Server-Side da programatik olarak oluşturulan Liste.

bulkCopy.BatchSize: Bir PageLevel de olacak olan row sayısıdır. bulkCopy.BatchSize: 10000; olarak set edildiğinde, her 10000 kayıtta ilgili List deki veriyi Database ye kaydeder.

bulkCopy.BulkCopyTimeout: DbCon timeout süresidir.

Bir önceki örnekte, bir tabloya *BulkInsert *ile veri aktarımını üzerine konuşmuştuk. Peki birden fazla tabloya *BulkInsert *ile veri aktarımı nasıl yapılır ? Bu sorunun birden fazla yöntem ile cevabı mümkündür. Bu araştırmanın amacı yüksek kapasitede veriyi çok kısa sürede database e aktararak maliyet ve zamanan kazanç olduğu için birazdan değineceğim yöntemi tercih ettim.

3 tane tablomuz olduğunu düşünelim.

alt

Öncelikle yapacağımız , bu 3 tablodaki verileri tek bir tabloda birleştirmek olacaktır.

alt

Tabloları birleştirirken, üye tipini ayırt etmek amaçlı olarak Tip adlı bir alan açtığımızı düşünelim. Diğer alanlar ise üye ve yönetici alanlarının birleşimi olacaktır.

Elimizdeki verileri, bu tabloya uygun formatta BulkInsert ile hızlıca aktarabilir. Böylece,Application <-> Database arası maliyet ve zaman kazancı mümkün olacaktır. Peki buradan sonra ne yapılabilir. Database de bu kayıtları Kişi-Üye-Yönetici olacak şekilde tutmak için ne yapılabilir?

Buradan sonra T-Sql Programaticly Structures bize yardımcı olabilir. StoredProcedure ve View ler bu iş için kullanışlı olacaktır.

Kayıtların Üye mi yoksa Yönetici kaydı mı olduğunu anlamak için ise Tip değişkeni üzerinden T-sql ile kontrol mümkün olacaktır. Stored procedure lerimizde ilgili conditionlar bu alan değerine göre kayıtları ayırabilir.

Sonuç

2000 li yıllardan itibaren Büyük Veri(BigData) yi efektif şekilde işlek büyük önem arz etmektedir. BulkInsert yöntemi günümüzde bu sorunun çözümü için kullanılan popüler yöntemlerden biri olarak karşımıza çıkmaktadır. Bu alanda database tarafındaki programatik yapının da(Stored Func/View, Constraints) yardımcı olabileceği düşünülmektedir. Yapılan araştırmalara 1.000.000 tane verinin saniyeler içerisinde bu yöntemler ile veritabanına aktarılabildiği kanıtlanmıştır.

Bu konu hakkında daha detaylı bilgi almak isteyen kişiler için aşağıda paylaştığım ek linkler faydalı olabilir.

http://stackoverflow.com/questions/24877240/fastest-way-to-insert-1-million-rows-in-sql-server

https://www.codeproject.com/Articles/25457/Multiple-Ways-to-do-Multiple-Inserts#_Toc196622240

https://social.msdn.microsoft.com/Forums/sqlserver/en-US/b1476847-7897-465d-b392-bf5ca67f8ffb/inserting-about-a-billion-rows-in-one-table-in-about-4-hours?forum=sqldataaccess

http://stackoverflow.com/questions/5296106/how-to-copy-a-huge-table-data-into-another-table-in-sql-server

http://sqlmag.com/t-sql/adventures-big-data-how-import-16-billion-rows-single-table

https://www.quora.com/I-have-a-table-that-has-1-3-billion-sales-rows-and-most-of-the-columns-are-indexed-It-still-takes-a-long-time-for-me-to-run-a-procedure-or-a-view-even-with-conditions-How-do-I-solve-the-issue

https://weblog.west-wind.com/posts/2013/Dec/22/Entity-Framework-and-slow-bulk-INSERTs

http://stackoverflow.com/questions/5052958/libraries-for-ado-net-to-rapidly-bulk-insert-data-into-a-database-from-a-csv-fi

http://stackoverflow.com/questions/18841000/sql-bulk-copy-insert-in-c-sharp

Kaynakça:

https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy(v=vs.110).aspx

https://social.msdn.microsoft.com/Forums/sqlserver/en-US/4347510a-fcb1-4050-a457-0b79c211b465/compare-bulk-insert-vs-insert?forum=transactsql

http://searchsqlserver.techtarget.com/definition/relational-database-management-system

https://venzi.wordpress.com/2012/03/31/loading-data-fast-regular-insert-vs-bulk-insert/