Migrasi data bocor dari CSV ke PostgreSQL

 Assalamu'alaikum wr. wb

Belum lama sebuah berita heboh mengenai bocornya identitas dari penduduk Indonesia sebanyak 279 juta yang ditawarkan di sebuah forum online.



Hasil investigasi yang dimuat dari salah satu media online menyebutkan bahwa data tersebut berasal dari BPJS (https://tirto.id/hasil-investigasi-kominfo-kebocoran-data-dari-bpjs-kesehatan-ggbX)



Berbekal dari sampel data yang diberikan dan statement dari berita di atas, bahwa dari sebanyak 1 juta sampel data "hanya" terdapat 100 ribuan data saja. Sampel kebocoran tersebut dishare di forum online tersebut dan bisa didowload dari 3 server yang berbeda. Data tersebut dikompres dengan format .zip ini memiliki besar kurang lebih 50MB. 

Dalam berita di atas disebut bahwa data dalam format tabel Excel. Sebenarnya format sampel yang dishare adalah format CSV, yakni Comma Seperated Value bukan format Excel. Format CSV sendiri sudah ama lahir sebelum muncul Excel. Saat ini teks dengan format CSV bukan hanya merujuk pada data yang hanya dipisahkan dengan tanda koma. Namun lebih umum sehingga ada yang menyebut CSV sebagai Column Seperated Value dimana Column nya merupakan delimiter yang bisa menggunakan berbagai macam karakter selain koma.

File .zip yang telah didownload tersebut, memiliki password maka perlu di ekstrak dengan aplikasi yang mendukung. Di Linux bisa digunakan perintah  "$ 7z x -praidforums Indonesia.zip" untuk melakukan ekstraksi. Hasil dari ekstraksi ini adalah file berformat CSV dengan nama Untitled.csv dengan ukuran kurang lebih 242MB. Untuk melihat jumlah recordnya bisa dilihat dengan menggunakan teks editor seperti vi dan memperhatikan informasi yang ada di bagian bawah.


Dari gambar nampak bahwa jumlah bari dari file .csv tersebut adalah 1.000.003 baris. Namun demikian dari berita di atas disebut bahwa data yang ada dalam file tersebut "hanya" 100 ribuan. Untuk memastikan hal tersebut maka cara yang paling mudah adalah mengimport kedalam program spreadsheet seperti Excel atau ke database seperti PostgreSQL.

Untuk membawa ke PostgreSQL maka langkah pertama adalah membuat tabel dengan menyesuaikan tipe data yang ada dalam file .csv tersebut. Paling mudah bisa dilakukan dengan membuat seluruh tipedatanya adalah TEXT. Berikut contoh perintah membuat tabel untuk data tersebut,

create table datasampel (no CHAR(16) PRiMARY KEY, no1 CHAR(16), no2 CHAR(16), nama VARCHAR(50), nama1 VARCHAR(50), jk CHAR, Agama CHAR, ttl VARCHAR(30), tgllhr DATE, flag1 CHAR, nohp VARCHAR(15), nik CHAR(16), noktp CHAR(16), tmt DATE, tat DATE, npwp CHAR(20), email VARCHar(50), noka VARCHAR(16), kd1 CHAR, kd2 CHAR(4), kd3 CHAR(4), kd4 CHAR(4), kd5 CHAR(4), kd6 CHAR(4), ts1 VARCHAR(30), ts2 VARCHAR(30), u VARCHAR(25), u1 VARCHAR(25), ts3 VARCHAR(30), daftar VARCHAR(5));

 Tentu saja basis datanya dibuat terlebih dahulu. Setelah tabel dibuat maka dalam PostgreSQL untuk melakukan import dari bentuk .csv bisa dilakukan dengan perintah COPY.

=> copy datasampel from data.csv CSV DELIMITER ','  QUOTE '"' ESCAPE '\';

Perlu diperhatikan format DATESTYLE nya karena ada tipe data DATE yang digunakan. Tabel di atas dibuat dengan asumsi bahwa data pada kolom-kolom tertentu sudah sesuai dengan kententuan atau dengan lebar data yang wajar.

Dari hasil import tidak bisa berhasil dengan sekali ujicoba. Beberapa lebar tipe data pada tabel ternyata tidak sesuai dengan data yang pada file .csv. Berikut kesalahan saat melakukan import,

ERROR:  value too long for type character varying(15)

CONTEXT:  COPY datasampel, line 2210, column nohp: "08966666666666666666"

ERROR:  value too long for type character(16)

CONTEXT:  COPY datasampel, line 2429, column noktp: "2171XXXXXXXXXXXX`"

ERROR:  value too long for type character(20)

CONTEXT:  COPY datasampel, line 2884, column noktp: "3670000000000000000000"

ERROR:  value too long for type character(20)

CONTEXT:  COPY datasampel, line 3069, column npwp: "24.XXX.XXX.X--XXX.XXX"

ERROR:  extra data after last expected column

CONTEXT:  COPY datasampel, line 488300: ""0001XXXXXXXXX"," "," ","******** *****","******** *****","1","0","AMAR\","1/1/1753","1",,," ","1/1/..."

ERROR:  value too long for type character varying(30)

CONTEXT:  COPY datasampel, line 5878, column ttl: "DESA LOLOAN BARAT, AWEN LELATENG"

ERROR:  extra data after last expected column


ERROR:  value too long for type character(30)

CONTEXT:  COPY datasampel, line 53735, column noktp: "110XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"


CONTEXT:  COPY datasampel, line 197766, column nama: "HADIXXXX(nik gd terdaftar pensiun XXX no kartu 00000XXXXXXXX)"


ERROR:  value too long for type character varying(50)

CONTEXT:  COPY datasampel, line 197766, column nama1: "HADIXXXX(nik gd terdaftar pensiun XXX no kartu 00000XXXXXXXX)"

Nampak bahwa data yang ada di file .csv merupakan data "kotor" dimana terdapat banyak data yang tidak konsisten lebar datanya khususnya pada kolom yan harusnya memiliki lebar yang sama. Demikian pula adanya catatan di kolom nama, adanya tanda \ di beberapa kolom yang menyebabkan kegagalan dalam proses import.
Hal tersebut bisa menjadi kabar “baik” atau juga kabar “buruk”. Kabar baiknya bisa jadi data yang dijual ini hanya data “dummy” atau data ujicoba. Kabar buruknya jika data ini disedot dari sistem yang “live” maka nampak betapa buruk desain basis data yang digunakan.
Setelah tipedata tabel disesuaikan maka seluruh baris data sebanyak 1 juta record berhasil diimport ke PostgreSQL.

dataDB=> select count(*) from datasampel ;

  count  

---------

 1000000

(1 row)


Namun merujuk pada informasi berita di atas maka perlu dilihat lebih detail dari 1 juta record tersebut, misal dilihat berapa bvanyak data yang niknya bernilai NULL.

dataDB=> select count(*) from datasampel where nik is NULL;

 count  

--------

 625873

(1 row)


Nampak bawah cukup banyak (625.873) record tanpa memiliki NIK, bisa jadi benar bahwa data yang "bersih" dari sampel yang dijual tersebut "hanya" 100 an ribuan record


Wassalamu'alaikum wr. wb

Komentar

Postingan populer dari blog ini

Membuat Web Directory dengan Drupal

Membandingkan Kecepatan Web PT di Yogyakarta