Tutorial HDFS untuk Analis Data yang Terjebak dengan Basis Data Relasional
Diterbitkan: 2022-03-11pengantar
Sekarang, Anda mungkin pernah mendengar tentang Hadoop Distributed File System (HDFS), terutama jika Anda adalah analis data atau seseorang yang bertanggung jawab untuk memindahkan data dari satu sistem ke sistem lainnya. Namun, apa manfaat yang dimiliki HDFS dibandingkan database relasional?
HDFS adalah solusi sumber terbuka yang dapat diskalakan untuk menyimpan dan memproses data dalam jumlah besar. HDFS telah terbukti andal dan efisien di banyak pusat data modern.
HDFS menggunakan perangkat keras komoditas bersama dengan perangkat lunak sumber terbuka untuk mengurangi biaya keseluruhan per byte penyimpanan.
Dengan replikasi bawaan dan ketahanannya terhadap kegagalan disk, HDFS adalah sistem yang ideal untuk menyimpan dan memproses data untuk analitik. Itu tidak memerlukan dasar-dasar dan overhead untuk mendukung atomisitas transaksi, konsistensi, isolasi, dan daya tahan (ACID) seperti yang diperlukan dengan sistem database relasional tradisional.
Selain itu, jika dibandingkan dengan database perusahaan dan komersial, seperti Oracle, penggunaan Hadoop sebagai platform analitik dapat menghindari biaya lisensi tambahan.
Salah satu pertanyaan yang diajukan banyak orang ketika pertama kali belajar tentang HDFS adalah: Bagaimana cara memasukkan data saya yang sudah ada ke dalam HDFS?
Pada artikel ini, kita akan membahas cara mengimpor data dari database PostgreSQL ke HDFS. Kami akan menggunakan Apache Sqoop, yang saat ini merupakan solusi open source yang paling efisien untuk mentransfer data antara HDFS dan sistem database relasional. Apache Sqoop dirancang untuk memuat data secara massal dari database relasional ke HDFS (impor) dan untuk menulis data secara massal dari HDFS ke database relasional (ekspor).
Langkah-langkah dalam tutorial ini ditulis untuk seseorang dengan pengetahuan dasar mengeksekusi query SQL dan pengetahuan dasar tentang perintah HDFS.
Sistem database yang digunakan adalah PostgreSQL 9.5 untuk Windows, dan versi HDFS adalah Cloudera Hadoop 2.5.0-cdh5.2.0 pada mesin virtual Centos 6.4 Linux.
Apache Sqoop bergantung pada file JAR driver JDBC yang khusus untuk vendor database relasional dan versi database.
Untuk menjalankan langkah-langkah yang ditunjukkan dalam artikel ini, pengguna akan memerlukan izin untuk terhubung dari jarak jauh ke database PostgreSQL, izin SELECT
pada database relasional, izin menulis pada HDFS, dan menjalankan izin pada Sqoop yang dapat dieksekusi.
Untuk tujuan tutorial ini, kami membuat database PostgreSQL, menamakannya Toptal , dan membuatnya dapat diakses melalui port 5432.
Sumber Data PostgreSQL
Untuk memulai, di database PostgreSQL Toptal
kami, kami akan membuat tabel data pengujian bernama sales
. Kami akan berasumsi bahwa sertifikat OpenSSL dan file kunci pribadi sudah ada di server PostgreSQL.
Server [localhost]: Database [postgres]: Toptal Port [5432]: Username [postgres]: Password for user postgres: psql (9.5.3) Toptal=# create table sales Toptal-# ( Toptal(# pkSales integer constraint salesKey primary key, Toptal(# saleDate date, Toptal(# saleAmount money, Toptal(# orderID int not null, Toptal(# itemID int not null Toptal(# ); CREATE TABLE
Selanjutnya, kita akan memasukkan 20 baris ke dalam tabel:
Toptal=# insert into sales values (1, '2016-09-27', 1.23, 1, 1); INSERT 0 1 Toptal=# insert into sales values (2, '2016-09-27', 2.34, 1, 2); INSERT 0 1 Toptal=# insert into sales values (3, '2016-09-27', 1.23, 2, 1); INSERT 0 1 Toptal=# insert into sales values (4, '2016-09-27', 2.34, 2, 2); INSERT 0 1 Toptal=# insert into sales values (5, '2016-09-27', 3.45, 2, 3); INSERT 0 1 Toptal=# insert into sales values (6, '2016-09-28', 3.45, 3, 3); INSERT 0 1 Toptal=# insert into sales values (7, '2016-09-28', 4.56, 3, 4); INSERT 0 1 Toptal=# insert into sales values (8, '2016-09-28', 5.67, 3, 5); INSERT 0 1 Toptal=# insert into sales values (9, '2016-09-28', 1.23, 4, 1); INSERT 0 1 Toptal=# insert into sales values (10, '2016-09-28', 1.23, 5, 1); INSERT 0 1 Toptal=# insert into sales values (11, '2016-09-28', 1.23, 6, 1); INSERT 0 1 Toptal=# insert into sales values (12, '2016-09-29', 1.23, 7, 1); INSERT 0 1 Toptal=# insert into sales values (13, '2016-09-29', 2.34, 7, 2); INSERT 0 1 Toptal=# insert into sales values (14, '2016-09-29', 3.45, 7, 3); INSERT 0 1 Toptal=# insert into sales values (15, '2016-09-29', 4.56, 7, 4); INSERT 0 1 Toptal=# insert into sales values (16, '2016-09-29', 5.67, 7, 5); INSERT 0 1 Toptal=# insert into sales values (17, '2016-09-29', 6.78, 7, 6); INSERT 0 1 Toptal=# insert into sales values (18, '2016-09-29', 7.89, 7, 7); INSERT 0 1 Toptal=# insert into sales values (19, '2016-09-29', 7.89, 8, 7); INSERT 0 1 Toptal=# insert into sales values (20, '2016-09-30', 1.23, 9, 1); INSERT 0 1
Mari pilih data untuk memverifikasi bahwa data terlihat benar:
Toptal=# select * from sales; pksales | saledate | saleamount | orderid | itemid ---------+------------+------------+---------+-------- 1 | 2016-09-27 | $1.23 | 1 | 1 2 | 2016-09-27 | $2.34 | 1 | 2 3 | 2016-09-27 | $1.23 | 2 | 1 4 | 2016-09-27 | $2.34 | 2 | 2 5 | 2016-09-27 | $3.45 | 2 | 3 6 | 2016-09-28 | $3.45 | 3 | 3 7 | 2016-09-28 | $4.56 | 3 | 4 8 | 2016-09-28 | $5.67 | 3 | 5 9 | 2016-09-28 | $1.23 | 4 | 1 10 | 2016-09-28 | $1.23 | 5 | 1 11 | 2016-09-28 | $1.23 | 6 | 1 12 | 2016-09-29 | $1.23 | 7 | 1 13 | 2016-09-29 | $2.34 | 7 | 2 14 | 2016-09-29 | $3.45 | 7 | 3 15 | 2016-09-29 | $4.56 | 7 | 4 16 | 2016-09-29 | $5.67 | 7 | 5 17 | 2016-09-29 | $6.78 | 7 | 6 18 | 2016-09-29 | $7.89 | 7 | 7 19 | 2016-09-29 | $7.89 | 8 | 7 20 | 2016-09-30 | $1.23 | 9 | 1 (20 rows)
Datanya terlihat bagus, jadi mari kita lanjutkan.
Impor ke HDFS Menggunakan Sqoop
Dengan sumber data yang ditentukan, kami sekarang siap untuk mengimpor data ke dalam HDFS. Perintah sqoop
yang akan kita periksa tercantum di bawah ini, dan kita akan memecah setiap argumen dalam poin-poin berikut. Perhatikan bahwa perintah seharusnya berada pada satu baris lengkap atau, seperti yang ditunjukkan di bawah, dengan garis miring terbalik (karakter kelanjutan baris perintah Linux) di akhir setiap baris kecuali yang terakhir.
sqoop import --connect 'jdbc:postgresql://aaa.bbb.ccc.ddd:5432/Toptal?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory' \ --username 'postgres' -P \ --table 'sales' \ --target-dir 'sales' \ --split-by 'pksales'
-
sqoop import
- Eksekusi bernamasqoop
, dan kami menginstruksikannya untuk mengimpor data dari tabel atau tampilan dari database ke HDFS. -
--connect
- Dengan argumen--connect
, kita meneruskan string connect JDBC untuk PostgreSQL. Dalam hal ini, kami menggunakan alamat IP, nomor port, dan nama database. Kami juga perlu menentukan bahwa SSL sedang digunakan dan perlu menyediakan kelasSSLSocketFactory
untuk digunakan. -
--username
- Dalam contoh ini, nama pengguna adalah login PostgreSQL, bukan login Windows. Pengguna harus memiliki izin untuk terhubung ke database yang ditentukan dan untuk memilih dari tabel yang ditentukan. -
-P
- Ini akan meminta pengguna baris perintah untuk memasukkan kata sandi. Jika Sqoop jarang dieksekusi, ini mungkin pilihan yang bagus. Ada beberapa cara lain untuk meneruskan kata sandi ke perintah secara otomatis, tetapi kami mencoba membuatnya sederhana untuk artikel ini. -
--table
- Di sinilah kita meneruskan nama tabel PostgreSQL. -
--target-dir
- Argumen ini menentukan direktori HDFS tempat data akan disimpan. -
--split-by
- Kami harus memberi Sqoop pengenal unik untuk membantunya mendistribusikan beban kerja. Kemudian dalam output pekerjaan, kita akan melihat di mana Sqoop memilih nilai minimum dan maksimum untuk membantu menetapkan batas pemisahan.
Sebaiknya letakkan perintah dalam skrip untuk tujuan pengulangan dan pengeditan, seperti yang ditunjukkan di bawah ini:
[hdfs@localhost:/sqoop]$ cat sqoopCommand.sh sqoop import --connect 'jdbc:postgresql://aaa.bbb.ccc.ddd:5432/toptal?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory' \ --username 'postgres' -P \ --table 'sales' \ --target-dir 'sales' \ --split-by 'pksales' [hdfs@localhost:/sqoop]$
Sekarang, saatnya menjalankan skrip perintah Sqoop di atas. Output dari perintah Sqoop ditunjukkan di bawah ini.
[hdfs@localhost:/sqoop]$ ./sqoopCommand.sh 16/10/02 18:58:34 INFO sqoop.Sqoop: Running Sqoop version: 1.4.5-cdh5.2.0 Enter password: 16/10/02 18:58:40 INFO manager.SqlManager: Using default fetchSize of 1000 16/10/02 18:58:40 INFO tool.CodeGenTool: Beginning code generation 16/10/02 18:58:41 INFO manager.SqlManager: Executing SQL statement: SELECT t.* FROM "sales" AS t LIMIT 1 16/10/02 18:58:41 INFO orm.CompilationManager: HADOOP_MAPRED_HOME is /usr/lib/hadoop-0.20-mapreduce Note: /tmp/sqoop-training/compile/77f9452788024792770d52da72ae871f/sales.java uses or overrides a deprecated API. Note: Recompile with -Xlint:deprecation for details. 16/10/02 18:58:43 INFO orm.CompilationManager: Writing jar file: /tmp/sqoop-training/compile/77f9452788024792770d52da72ae871f/sales.jar 16/10/02 18:58:43 WARN manager.PostgresqlManager: It looks like you are importing from postgresql. 16/10/02 18:58:43 WARN manager.PostgresqlManager: This transfer can be faster! Use the --direct 16/10/02 18:58:43 WARN manager.PostgresqlManager: option to exercise a postgresql-specific fast path. 16/10/02 18:58:43 INFO mapreduce.ImportJobBase: Beginning import of sales 16/10/02 18:58:45 WARN mapred.JobClient: Use GenericOptionsParser for parsing the arguments. Applications should implement Tool for the same. 16/10/02 18:58:46 INFO db.DBInputFormat: Using read commited transaction isolation 16/10/02 18:58:46 INFO db.DataDrivenDBInputFormat: BoundingValsQuery: SELECT MIN("pksales"), MAX("pksales") FROM "sales" 16/10/02 18:58:47 INFO mapred.JobClient: Running job: job_201609280401_0005 16/10/02 18:58:48 INFO mapred.JobClient: map 0% reduce 0% 16/10/02 18:59:04 INFO mapred.JobClient: map 50% reduce 0% 16/10/02 18:59:14 INFO mapred.JobClient: map 75% reduce 0% 16/10/02 18:59:15 INFO mapred.JobClient: map 100% reduce 0% 16/10/02 18:59:18 INFO mapred.JobClient: Job complete: job_201609280401_0005 16/10/02 18:59:18 INFO mapred.JobClient: Counters: 23 16/10/02 18:59:18 INFO mapred.JobClient: File System Counters 16/10/02 18:59:18 INFO mapred.JobClient: FILE: Number of bytes read=0 16/10/02 18:59:18 INFO mapred.JobClient: FILE: Number of bytes written=1190344 16/10/02 18:59:18 INFO mapred.JobClient: FILE: Number of read operations=0 16/10/02 18:59:18 INFO mapred.JobClient: FILE: Number of large read operations=0 16/10/02 18:59:18 INFO mapred.JobClient: FILE: Number of write operations=0 16/10/02 18:59:18 INFO mapred.JobClient: HDFS: Number of bytes read=438 16/10/02 18:59:18 INFO mapred.JobClient: HDFS: Number of bytes written=451 16/10/02 18:59:18 INFO mapred.JobClient: HDFS: Number of read operations=4 16/10/02 18:59:18 INFO mapred.JobClient: HDFS: Number of large read operations=0 16/10/02 18:59:18 INFO mapred.JobClient: HDFS: Number of write operations=4 16/10/02 18:59:18 INFO mapred.JobClient: Job Counters 16/10/02 18:59:18 INFO mapred.JobClient: Launched map tasks=4 16/10/02 18:59:18 INFO mapred.JobClient: Total time spent by all maps in occupied slots (ms)=48877 16/10/02 18:59:18 INFO mapred.JobClient: Total time spent by all reduces in occupied slots (ms)=0 16/10/02 18:59:18 INFO mapred.JobClient: Total time spent by all maps waiting after reserving slots (ms)=0 16/10/02 18:59:18 INFO mapred.JobClient: Total time spent by all reduces waiting after reserving slots (ms)=0 16/10/02 18:59:18 INFO mapred.JobClient: Map-Reduce Framework 16/10/02 18:59:18 INFO mapred.JobClient: Map input records=20 16/10/02 18:59:18 INFO mapred.JobClient: Map output records=20 16/10/02 18:59:18 INFO mapred.JobClient: Input split bytes=438 16/10/02 18:59:18 INFO mapred.JobClient: Spilled Records=0 16/10/02 18:59:18 INFO mapred.JobClient: CPU time spent (ms)=3980 16/10/02 18:59:18 INFO mapred.JobClient: Physical memory (bytes) snapshot=481574912 16/10/02 18:59:18 INFO mapred.JobClient: Virtual memory (bytes) snapshot=2949685248 16/10/02 18:59:18 INFO mapred.JobClient: Total committed heap usage (bytes)=127401984 16/10/02 18:59:18 INFO mapreduce.ImportJobBase: Transferred 451 bytes in 33.7555 seconds (13.3608 bytes/sec) 16/10/02 18:59:18 INFO mapreduce.ImportJobBase: Retrieved 20 records. [hdfs@localhost:/sqoop]$
Perhatikan baris terakhir dari output di atas menunjukkan bahwa 20 record diambil, yang sesuai dengan 20 record dalam tabel di database PostgreSQL.

Setelah menjalankan perintah Sqoop, kita dapat menjalankan perintah hdfs dfs -ls
untuk melihat direktori yang telah dibuat secara default dengan nama tabel pada HDFS.
[hdfs@localhost:/sqoop]$ hdfs dfs -ls Found 1 items drwxrwxrwx - toptal data 0 2016-10-02 18:59 sales [hdfs@localhost:/sqoop]$
Kita dapat menggunakan perintah hdfs dfs -ls
lagi untuk membuat daftar isi direktori sales
. Jika Anda melihat pada HDFS, Anda dapat melihat bahwa data dipartisi dan tersebar di empat file secara default, tidak hanya berisi satu.
[hdfs@localhost:/sqoop]$ hdfs dfs -ls sales Found 6 items -rw-rw-rw- 1 toptal data 0 2016-10-02 18:59 sales/_SUCCESS drwxrwxrwx - toptal data 0 2016-10-02 18:58 sales/_logs -rw-rw-rw- 1 toptal data 110 2016-10-02 18:59 sales/part-m-00000 -rw-rw-rw- 1 toptal data 111 2016-10-02 18:59 sales/part-m-00001 -rw-rw-rw- 1 toptal data 115 2016-10-02 18:59 sales/part-m-00002 -rw-rw-rw- 1 toptal data 115 2016-10-02 18:59 sales/part-m-00003 [hdfs@localhost:/sqoop]$
Perintah hdfs dfs -cat
akan menampilkan semua record di partisi pertama dari data penjualan di HDFS.
[hdfs@localhost:/sqoop]$ hdfs dfs -cat sales/part-m-00000 1,2016-09-27,1.23,1,1 2,2016-09-27,2.34,1,2 3,2016-09-27,1.23,2,1 4,2016-09-27,2.34,2,2 5,2016-09-27,3.45,2,3 [hdfs@localhost:/sqoop]$
Perhatikan bahwa pembatas file default adalah koma. Juga, perhatikan bahwa hanya ada lima baris di setiap partisi, karena 20 baris dalam sumber telah didistribusikan secara merata di keempat partisi.
Untuk membatasi jumlah baris yang di-output ke layar, kita dapat mem-pipe output dari perintah cat
ke perintah head
seperti yang ditunjukkan di bawah ini, untuk memeriksa isi dari tiga partisi lainnya.
Argumen -n 5
ke perintah head
membatasi output layar ke lima baris pertama.
(Perhatikan bahwa dalam kasus kami, ini tidak perlu karena hanya ada lima baris di setiap partisi untuk memulai. Namun, dalam praktiknya, Anda mungkin akan memiliki lebih banyak baris daripada ini di setiap partisi dan akan ingin memeriksa beberapa baris pertama untuk pastikan mereka terlihat benar, jadi ini menunjukkan cara melakukannya.)
[hdfs@localhost:/sqoop]$ hdfs dfs -cat sales/part-m-00001 |head -n 5 6,2016-09-28,3.45,3,3 7,2016-09-28,4.56,3,4 8,2016-09-28,5.67,3,5 9,2016-09-28,1.23,4,1 10,2016-09-28,1.23,5,1 [hdfs@localhost:/sqoop]$ hdfs dfs -cat sales/part-m-00002 |head -n 5 11,2016-09-28,1.23,6,1 12,2016-09-29,1.23,7,1 13,2016-09-29,2.34,7,2 14,2016-09-29,3.45,7,3 15,2016-09-29,4.56,7,4 [hdfs@localhost:/sqoop]$ hdfs dfs -cat sales/part-m-00003 |head -n 5 16,2016-09-29,5.67,7,5 17,2016-09-29,6.78,7,6 18,2016-09-29,7.89,7,7 19,2016-09-29,7.89,8,7 20,2016-09-30,1.23,9,1 [hdfs@localhost:/sqoop]$
Jika Anda perlu menjalankan kueri untuk mengekstrak data dari beberapa tabel di database PostgreSQL, ini dapat dilakukan dengan perintah berikut:
[hdfs@localhost:/sqoop]$ cat sqoopCommand.sh sqoop import --connect 'jdbc:postgresql://aaa.bbb.ccc.ddd:5432/toptal?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory' \ --username 'postgres' -P \ --target-dir 'creditCardOrders' \ --split-by 'pksales' \ --query "select s.pksales, s.saledate, s.saleamount, o.shippingtype, o.methodofpayment from sales s inner join orders o on s.orderid=o.orderid where o.methodofpayment='credit card' and \$CONDITIONS" [hdfs@localhost:/sqoop]$
Dalam perintah di atas, kami menggunakan beberapa argumen yang sama untuk perintah Sqoop, tetapi mereka memiliki kepentingan yang berbeda ketika digunakan dengan perintah SQL.
-
--target-dir
- Direktori target memberi tahu Sqoop di direktori mana pada HDFS untuk menyimpan data yang dipilih. Argumen ini diperlukan oleh Sqoop saat menggunakan kueri bentuk bebas. -
--split-by
- Meskipun kami memilih kunci utama dari tabel penjualan, kami masih harus memberikan pengidentifikasi unik kepada Sqoop untuk membantunya mendistribusikan beban kerja. -
--query
- Ini adalah argumen di mana kami menyediakan kueri SQL. Kueri di atas diapit dalam tanda kutip ganda. Perhatikan bahwa tidak ada garis miring terbalik (karakter kelanjutan baris) di beberapa baris yang berisi kueri. Perhatikan jugaand \$CONDITIONS
di akhir klausaWHERE
. Ini diperlukan oleh Sqoop karena Sqoop akan secara otomatis mengganti token$CONDITIONS
dengan ekspresi unik.
Masalah atau Tidak Ada Masalah: Anda Harus Mempertimbangkan HDFS
HDFS memiliki banyak keunggulan dibandingkan database relasional. Jika Anda melakukan analisis data, Anda harus mempertimbangkan untuk memigrasikan data Anda ke HDFS, hari ini.
Dengan keterampilan yang dipelajari di sini, mengimpor data dari sistem basis data relasional ke HDFS adalah proses yang sederhana dan mudah yang dapat diselesaikan dengan satu perintah. Meskipun contoh-contoh ini memiliki sejumlah kecil baris, mekanisme mengimpor data dalam jumlah besar ke HDFS dari tabel database PostgreSQL tetap sama.
Anda bahkan dapat bereksperimen dengan mengimpor tabel besar dan memvariasikan pembatas penyimpanan. Menggunakan Apache Sqoop lebih efisien daripada mengekspor data database ke file, mentransfer file dari server database ke HDFS, dan kemudian memuat file ke HDFS.