SQL Server Indonesia User Groups Community January 2009 - Posts - drowned in code

SQL Server Indonesia User Groups Community

SQL Server Indonesia User Groups Community
Welcome to SQL Server Indonesia User Groups Community Sign in | Join | Help
in Search

drowned in code

eat, sleep, breath, SQL

January 2009 - Posts

  • Menyaksikan Proses Terjadinya Transformasi dengan Data Viewer

    download sample code

    Beberapa waktu yang lalu saya mempelajari sesuatu yang sangat berharga dan bermanfaat dari seorang teman. Dia, kita sebut saja namanya Indra (nama sebenarnya, hehe), menunjukkan pada saya bagaimana caranya melihat transformasi data pada saat sebuah SSIS package dieksekusi dengan menggunakan Data Viewer.

    Dahulu, sebelum tahu tentang Data Viewer saya selalu menggunakan cara yang melelahkan pada saat ingin melihat transformasi data. Pertama kali bekerja dengan SSIS saya melihatnya dengan menggunakan Script Component, lalu menampilkan data yang ingin saya lihat dengan library MessageBox. Masalah dengan MessageBox dan Script Component (dan ketidakkreatifan saya dalam menggunakannya) adalah bahwa saya harus membuat banyak Script Component di tempat-tempat transformasi yang ingin saya lihat dan MessageBox-nya muncul untuk setiap baris data yang ditransformasikan. Mungkin tidak akan menjadi masalah jika hanya 10 atau 20 baris data yang ditrasnformasi, tapi bayangkan jika ada satu juta baris data.

    image

    Lalu setelah beberapa lama kelelahan dengan MessageBox, saya mengenal library bawaan SSIS untuk menampilkan informasi di tab progress/execution result yaitu FireInformation. Library tersebut tetap dipanggil dari Script Component dan tidak semelelahkan MessageBox. Akan tetapi, hal yang saya pelajari dari FireInformation adalah bahwa penggunaannya dapat memperlambat proses transformasi.

    image

    Akhirnya saya bertemu teman saya itu dan mempelajari mengenai Data Viewer. Data Viewer menampilkan data diantara dua component yang terdapat di data flow dan dapat menampilkan data pada saat di-extract dari data source, sebelum dan sesudah sebuah transformasi, dan sebelum datanya di-load ke dalam destination.

    Penggunaan data viewer untuk melihat data memudahkan kita untuk mengidentifikasi nilai data yang tidak diharapkan, melihat sebuah transformasi mengubah nilai pada sebuah column, dan menemukan alasan mengapa sebuah transformasi gagal.

    Data Viewer dapat menampilkan data dalam bentuk grid, histogram, scatter plot atau column chart. Silakan lihat Books Online untuk keterangan lebih detil mengenai bentuk-bentuk Data Viewer. Pada tulisan ini, saya ingin menunjukkan bagaimana menggunakannya untuk melihat transformasi pada blog sebelumnya mengenai men-generate data di DimDate.

    Pertama, buka package DimDate.dtsx pada project SampleDBETL lalu buka tab Data Flow.

    Klik kanan pada anak panah yang menghubungkan Script Component dan OLE DB Destination lalu pilih Data Viewers...

    image

    Klik button Add...

    image

    Pilih Grid sebagai tipe Data Viewer pada tab General

    image

    Buka tab Grid, lalu pilih kolom mana saja yang ingin ditampilkan. Secara default, Semua kolom yang terdapat pada metadata akan ditampilkan. Klik pada nama column dan gunakan tombol > dan < untuk memilih column mana yang akan ditampilkan dan yang tidak. Klik OK untuk menutup dialog Data Viewer dan klik tombol OK sekali lagi untuk menutup dialog Data Flow Path Editor

    image

    Pada saat dieksekusi, panel Data Viewer akan tampil dan proses transformasi akan berhenti ketika mencapai Data Viewer yang kita pasang tadi. Transformasi akan dilanjutkan pada saat tombol imageyang terdapat pada panel ditekan. Hal ini tentu memudahkan kita untuk melihat apakah datanya sudah sesuai dengan yang diinginkan atau belum.

    image

  • Mengisi Nilai Variable di dtexecui

    Untuk mengeksekusi sebuah SSIS package ada beberapa jalan yang bisa kita tempuh. Bisa menggunakan BIDS pada saat package-nya sedang di-develop, menggunakan dtexec untuk yang *** menggunakan command prompt atau dengan dtexecui untuk yang menyukai helper berbentuk GUI seperti saya. Dengan BIDS tentu akan mudah mengeset nilai sebuah variable pada saat akan dieksekusi, tapi bagaimana dengan dtexec atau dtexecui?

    image

    Pada dtexecui terdapat sebuah page bernama Set Values untuk mengeset nilai variable dan objek-objek lain pada package. Kolom property path berisi path dari sebuah properti dan kolom value berisi nilai path tersebut. Yang agak sulit dalam pengisiannya adalah karena page tersebut dibuat generic sehingga kita harus mengetahui nama properti objek yang akan diisi.

    Mengetahui Path Properti Sebuah Package

    Cara mudah untuk melihat properti sebuah package adalah dengan membuka package menggunakan BIDS dan melihat tab Package Explorer.

    image

    Gambar diatas adalah tab Package Explorer dari package DimDate yang saya buat pada blog sebelumnya. Sebagai contoh untuk mengisi value variable UserModifiedYear dengan 2010, maka property path nya diisi  \Package.Variables[User::UserModifiedYear].Value dan value berisi 2010

    image

    Pada saat package di-eksekusi dan kita cek table DimDate, akan ter-generate data untuk  tahun 2010

    image

  • Men-Generate Data Dimensi Waktu dengan SSIS

    Download sample code

    Apabila Anda pernah melihat atau membuat sebuah aplikasi Business Intelligence (BI), biasanya terdapat sebuah dimensi yang namanya DimDate atau DimTime yang berguna untuk menganalisis sebuah measure berdasarkan tanggal atau waktu.

    Untuk membuatnya tentu bermacam-macam cara yang bisa kita lakukan, dan yang paling saya *** adalah dengan menggunakan SSIS dan Script Component. Kenapa? Karena dengan script component yang notabene menggunakan VB atau C# sebagai programming language-nya memberikan keleluasan pada saat kita ingin membuat format penulisan tanggal dan bahasa yang digunakan sesuai dengan kebutuhan atau permintaan user.

    Sebagai ilustrasi bisa saja kita mengisi sebuah kolom dengan format [nama hari], [tanggal] [bulan] [tahun] dalam Bahasa Indonesia seperti Senin, 19 Januari 2009 atau Bahasa Inggris seperti Monday, January 19 2009. Hal ini dimungkinkan dengan adanya library CultureInfo yang memudahkan format penulisan tanggal.

    Spesifikasi

    Dalam contoh berikut, saya akan membuat sebuah dimensi waktu sederhana dengan nama DimDate dan men-generate datanya dalam setahun berdasarkan variable Tahun yang diisikan dengan input user ataupun otomatis mengikuti tahun berikutnya yang akan berjalan. Column yang terdapat pada DimDate adalah DateKey sebagai primary key, FullDate yang berisi tanggal, MonthName yang berisi nama bulan, DayName yang berisi nama hari, YearNumber, MonthNumberOfYear, DayNumberOfMonth yang masing-masih berisi tahun, bulan, dan tanggal.

    Membuat Database

    Pertama, kita buat dulu sebuah database dengan nama SampleDB ditambah dengan table DimDate didalamnya

    image

    Membuat Projek SSIS

    Buka Business Intelligence Development Studio (BIDS), buat sebuah SSIS Project baru dengan nama SampleDBETL

    image

    Tambahkan sebuah data source ke SampleDB

    image

    Ubah nama package.dtsx dengan DimDate.dtsx

    Tambahkan koneksi ke SampleDB pada connection manager DimDate.dtsx

    Variable

    Variable akan digunakan pada langkah selanjutnya yang isinya adalah tahun pada DimDate. Demi flexibilitas saya biasanya membuat dua variable. Yang pertama adalah UserModifiedYear yang dapat diisi oleh user apabila ingin men-generate data untuk tahun tertentu dan LogicalYear yang berisi tahun berikutnya apabila user tidak mengisi tahun pada UserModifiedYear.

    image

    LogicalYear sangat berguna pada saat DimDate ingin dijadikan sebuah job di SQL dan job nya akan di-schedule setahun sekali untuk men-generate data tahun berikutnya. Untuk mengisi nilai pada LogicalYear tentu kita dapat menggunakan expression. Pertama set properti EvaluateAsExpression untuk variable LogicalYear dengan True, lalu isi expression dengan @[User::UserModifiedYear] == 0 ?  YEAR(DATEADD("yy",1,GETDATE())) : @[User::UserModifiedYear]. Expression tersebut akan mengisi nilai LogicalYear dengan tahun berikutnya apabila UserModifiedYear berisi 0, dan berisi nilai UserModifiedYear apabila UserModifiedYear tidak berisi 0.

    image 

    Control Flow

    Di Control Flow kita buat sebuah Execute SQL Task yang isinya menghapus data di DimDate untuk tahun yang akan di-generate dan DataFlowTask untuk men-generate datanya.

    image

    Data Flow

    Di dataflow tambahkan script component yang tipenya adalah Source

    image

    Double click Script Component. Pada tab Inputs and Outputs, expand Output 0 > Output Columns lalu tambahkan 6 kolom sesuai dengan meng-klik tombol AddColumn.

    Nama Kolom Tipe Data Panjang
    FullDate DT_DATE  
    MonthName DT_STR 20
    DayName DT_STR 20
    YearNumber DT_I4  
    MonthNumberOfYear DT_I4  
    DayNumberOfMonth DT_I4  

    image

    Pada tab Script, tambahkan User::LogicalYear pada properti ReadOnlyVariables, pilih ScriptLanguage yang akan digunakan, apakah VB atau C#, lalu klik tombol Edit Script

    image

    Tambahkan script berikut pada sub/void CreateNewOutputRows() untuk mulai men-generate data DimDate

    VB

    Public Overrides Sub CreateNewOutputRows()
        Dim culture As New System.Globalization.CultureInfo("id-ID")
        Dim CurrentDate As New Date(Variables.LogicalYear, 1, 1)

        While CurrentDate.Year = Variables.LogicalYear
            Output0Buffer.AddRow()
            Output0Buffer.FullDate = CurrentDate
            Output0Buffer.MonthName = String.Format(culture, "{0:MMM}", CurrentDate)
            Output0Buffer.DayName = String.Format(culture, "{0:dddd}", CurrentDate)
            Output0Buffer.YearNumber = CurrentDate.Year
            Output0Buffer.MonthNumberOfYear = CurrentDate.Month
            Output0Buffer.DayNumberOfMonth = CurrentDate.Day
            CurrentDate = CurrentDate.AddDays(1)
        End While

        Output0Buffer.SetEndOfRowset()
    End Sub

     

    C#

    System.Globalization.CultureInfo culture = new System.Globalization.CultureInfo("id-ID");
    DateTime CurentDate = new DateTime(this.Variables.LogicalYear, 1, 1);
    while (CurentDate.Year == this.Variables.LogicalYear)
    {
        Output0Buffer.AddRow();
        Output0Buffer.FullDate = CurentDate;
        Output0Buffer.MonthName = String.Format(culture, "{0:MMMM}",CurentDate);
        Output0Buffer.DayName = string.Format(culture, "{0:dddd}",CurentDate);
        Output0Buffer.YearNumber = CurentDate.Year;
        Output0Buffer.MonthNumberOfYear = CurentDate.Month;
        Output0Buffer.DayNumberOfMonth = CurentDate.Day;
        CurentDate = CurentDate.AddDays(1);
    }
    Output0Buffer.SetEndOfRowset();

    Tutup script editor, lalu klik OK untuk menutup Script Component Editor

    Tambahkan OLE DB Destination ke dalam Data Flow, lalu hubungkan Script Component dan OLE DB Destination

    image

    Double clik OLE DB Destination, pilih SampleDB pada OLE DB connection manager, dan pilih [dbo].DimDate] sebagai table tujuan. Klik tab Mappings untuk me-map kolom pada Script Component dan kolom pada OLE DB Destination lalu klik OK untuk menutup OLE DB Destination Editor

    image

    Selesai! Apabila kita jalankan dan mengisi nilai UserModifiedYear dengan 2009, maka akan terbentuk 365 baris data untuk setiap hari yang ada di tahun ini.

    image

    Posted Jan 22 2009, 12:41 AM by si_hendrik with no comments
    Filed under:
  • Conquering SQL Server, Oracle, Windows Server 2003 on ia64 box

    Pada project saya yang lalu, saya diberi tugas untuk melakukan proses replikasi data dari SQL Server ke Oracle dengan menggunakan SSIS. Ini adalah project BI pertama yang saya kerjakan dan pengerjaanya memakan waktu yang lebih lama dari yang diperkirakan, kalau tidak ingin disebut sangat-sangat telat karena saya hanya diberi waktu tiga bulan sementara saya menyelesaikannya hampir 10 bulan (kebayang gak sih gimana marahnya bos dan client saya?)

    What took me so long?

    Yang pertama adalah karena saya tidak boleh menggunakan Replication yang terdapat di SQL Server karena client saya tersebut sudah memiliki Replication antara SQL Server dan SQL Server dan mereka tidak ingin proses Replication mereka menjadi terganggu.

    Kemudian terdapat incompatibility connectivity antara SQL Server dan Oracle. Jadi, pada saat saya menggunakan OLE DB provider Oracle untuk machine ia64 dan mencoba menggunakannya untuk melakukan query data dari SSIS atau SQL Server via Linked Server terdapat masalah pada saat me-return column-column dengan tipe data numeric/decimal. Workaround paling mudah adalah melakukan konversi ke char pada saat query ke oracle, lalu mengkonversi nya ke numeric dari SQL Server. Tapi saya tidak mau menggunakan cara ini karena membuat proses query menjadi lebih lama.

    Itu pada saat query, pada saat melakukan Insert, Update, dan Delete dari SSIS persoalan yang lain muncul. SSIS membutuhkan waktu yang sangat lama untuk melakukan transaksi. Sebagai ilustrasi, dibutuhkan waktu 30 menit untuk proses insert 100 ribu data sementara data yang harus di-insert jumlahnya jutaan. Berapa lama waktu eksekusi yang dibutuhkan?

    The Workaround

    Untungnya, saya dikasih dua buah box, yang satu x86 dan satu lagi ia64. jadilah saya pake dulu machine x86 untuk melakukan replikasi dan membuat senang bapak2 bos dan bapak2 client sambil berjanji dalam hati bahwa suatu hari nanti saya akan memindahkanya ke machine ia64.

    The Conquering

    Setelah tiga bulan melakukan research besar-besaran (yang terbesar yang pernah saya lakukan seumur hidup) dan tidak berhasil menemukan solusinya di internet, akhirnya titik terang muncul setelah saya berdiskusi dengan teman saya (a credit to iqbal, thanks yah bos) dan menyambangi beberapa site (yang bookmark nya hilang sekarang. huhuhu. Ternyata di luar sana juga banyak orang yang mengalami hal yang sama dengan saya).

    Jadi Oracle punya yang namanya Oracle Data Acces Component (ODAC) yang biasa digunakan untuk melakukan koneksi dari aplikasi yang dibuat dengan visual studio .net ke oracle, dan thanks god ada ODAC untuk IA64.

    Agar saya dapat meng-query data ke oracle dari SSIS, saya membuat sebuah custom component yang fungsinya sepert OLE DB Source. Provider nya menggunakan ODAC dan query nya seperti query biasa di oracle tanpa perlu melakukan konversi tipe data seperti menggunakan to_char.

    Untuk melakukan insert/update/delete, ternyata SSIS melakukan proses insert-commit untuk setiap row yang di-insert pada non Microsoft database. Pantas saja dibutuhkan setengah jam untuk 100 ribu data. Untuk menaklukannya, saya membuat component lain (dua buah untuk insert dan update, karena requirement nya adalah mengubah flag untuk data yang di-delete dari aktif menjadi tidak aktif). Lalu untuk setiap buffer di SSIS saya menggunakan transaction, jadi saya menambahkan statement begin transaction di awal buffer lalu meng-commit transaction di akhir buffer.

    Selain itu juga saya membuat custom component di control flow yang fungsinya seperti Execute SQL Task-nya SSIS karena ternyata Execute SQL Task tidak dapat digunakan untuk provider ODAC.

    Dengan bantuan ODAC dan custom component yang dapat kita buat menggunakan Visual Studio .net (C# atau VB) plus SQL Server SDK akhirnya project nya dapat selesai dengan cukup baik dan memuaskan (bagi saya pribadi dan bukan buat bos/client saya tentunya mungkin yah). Selain itu, proses eksekusi SSIS juga menjadi lebih cepat jika dibandingkan dengan menggunakan component bawaan SSIS.

More Posts
Powered by Community Server (Commercial Edition), by Telligent Systems