İlişkisel Veritabanlarında Sıkışmış Veri Analistleri İçin Bir HDFS Eğitimi

Yayınlanan: 2022-03-11

Tanıtım

Şimdiye kadar, özellikle veri analistiyseniz veya verileri bir sistemden diğerine taşımaktan sorumlu biriyseniz, muhtemelen Hadoop Dağıtılmış Dosya Sistemini (HDFS) duymuşsunuzdur. Ancak, HDFS'nin ilişkisel veritabanlarına göre faydaları nelerdir?

HDFS, büyük hacimli verileri depolamak ve işlemek için ölçeklenebilir, açık kaynaklı bir çözümdür. HDFS'nin birçok modern veri merkezinde güvenilir ve verimli olduğu kanıtlanmıştır.

HDFS, depolama bayt başına toplam maliyeti azaltmak için açık kaynaklı yazılımla birlikte ticari donanım kullanır.

Dahili replikasyonu ve disk arızalarına karşı dayanıklılığı ile HDFS, analitik için verileri depolamak ve işlemek için ideal bir sistemdir. Geleneksel ilişkisel veritabanı sistemlerinde gerektiği gibi, işlem atomiği, tutarlılık, yalıtım ve dayanıklılığı (ACID) desteklemek için temellere ve ek yüke ihtiyaç duymaz.

Ayrıca, Oracle gibi kurumsal ve ticari veritabanlarıyla karşılaştırıldığında, analitik platformu olarak Hadoop'u kullanmak, herhangi bir ekstra lisans maliyetini ortadan kaldırır.

Birçok kişinin HDFS'yi ilk öğrendiğinde sorduğu sorulardan biri şudur: Mevcut verilerimi HDFS'ye nasıl aktarırım?

Bu yazıda PostgreSQL veri tabanından HDFS'ye nasıl veri aktarılacağını inceleyeceğiz. HDFS ve ilişkisel veritabanı sistemleri arasında veri aktarımı için şu anda en verimli, açık kaynaklı çözüm olan Apache Sqoop'u kullanacağız. Apache Sqoop, verileri ilişkisel bir veritabanından HDFS'ye toplu olarak yüklemek (içe aktarma) ve verileri HDFS'den ilişkisel bir veritabanına toplu olarak yazmak (dışa aktarma) için tasarlanmıştır.

HDFS

Verilerinizi HDFS'ye geçirerek analitiği hızlandırın.
Cıvıldamak

Bu öğreticideki adımlar, temel SQL sorguları yürütme bilgisine ve temel HDFS komutları bilgisine sahip biri için yazılmıştır.

Kullanılan veritabanı sistemi Windows için PostgreSQL 9.5'tir ve HDFS sürümü, Centos 6.4 Linux sanal makinesinde Cloudera Hadoop 2.5.0-cdh5.2.0'dır.

Apache Sqoop, ilişkisel veritabanı satıcısına ve veritabanı sürümüne özgü JDBC sürücüsü JAR dosyalarına dayanır.

Bu makalede gösterilen adımları uygulamak için kullanıcının PostgreSQL veritabanına uzaktan bağlanma izinlerine, ilişkisel veritabanında SELECT izinlerine, HDFS'ye yazma izinlerine ve Sqoop yürütülebilir dosyasında yürütme izinlerine ihtiyacı olacaktır.

Bu öğreticinin amacı için, Toptal adlı bir PostgreSQL veritabanı oluşturduk ve onu 5432 numaralı bağlantı noktasından erişilebilir hale getirdik.

PostgreSQL Veri Kaynağı

Başlamak için PostgreSQL Toptal veritabanımızda sales adında bir test veri tablosu oluşturacağız. OpenSSL sertifikasının ve özel anahtar dosyalarının PostgreSQL sunucusunda zaten mevcut olduğunu varsayacağız.

 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

Ardından, tabloya 20 satır ekleyeceğiz:

 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

Verilerin doğru göründüğünü doğrulamak için verileri seçelim:

 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)

Veriler iyi görünüyor, o yüzden devam edelim.

Sqoop Kullanarak HDFS'ye Aktarın

Tanımlanan veri kaynağı ile artık verileri HDFS'ye aktarmaya hazırız. sqoop komutu aşağıda listelenmiştir ve her bir argümanı takip eden madde işaretlerinde inceleyeceğiz. Komutun tam bir satırda veya aşağıda gösterildiği gibi, sonuncusu hariç her satırın sonunda ters eğik çizgiyle (Linux komut satırı devam karakteri) olması gerektiğini unutmayın.

 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 - Yürütülebilir dosyanın adı sqoop ve biz ona verileri bir tablodan veya bir veri tabanından HDFS'ye aktarması talimatını veriyoruz.
  • --connect - --connect argümanıyla, PostgreSQL için JDBC bağlantı dizesini geçiyoruz. Bu durumda IP adresini, port numarasını ve veritabanı adını kullanırız. Ayrıca SSL'nin kullanıldığını belirtmemiz ve kullanılacak SSLSocketFactory sınıfını sağlamamız gerekiyor.
  • --username - Bu örnekte, kullanıcı adı bir Windows oturumu değil, bir PostgreSQL oturum açma işlemidir. Kullanıcı, belirtilen veritabanına bağlanma ve belirtilen tablodan seçim yapma izinlerine sahip olmalıdır.
  • -P - Bu, komut satırı kullanıcısından parola isteyecektir. Sqoop nadiren çalıştırılıyorsa, bu iyi bir seçenek olabilir. Parolayı otomatik olarak komuta geçirmenin birden çok yolu vardır, ancak bu makale için bunu basit tutmaya çalışıyoruz.
  • --table - Burası PostgreSQL tablosunun adını geçtiğimiz yer.
  • --target-dir - Bu argüman, verilerin depolanacağı HDFS dizinini belirtir.
  • --split-by - İş yükünü dağıtmasına yardımcı olmak için Sqoop'a benzersiz bir tanımlayıcı sağlamalıyız. İş çıktısının ilerleyen bölümlerinde, Sqoop'un bölünmüş sınırları belirlemeye yardımcı olmak için minimum ve maksimum değerleri nerede seçtiğini göreceğiz.

Aşağıda gösterildiği gibi, tekrarlanabilirlik ve düzenleme amacıyla komutu bir komut dosyasına koymak iyi bir fikirdir:

 [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]$

Şimdi, yukarıdaki Sqoop komut betiğini çalıştırmanın zamanı geldi. Sqoop komutunun çıktısı aşağıda gösterilmiştir.

 [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]$

Yukarıdaki çıktının son satırının, PostgreSQL veritabanındaki tablodaki 20 kayda karşılık gelen 20 kaydın alındığını gösterdiğine dikkat edin.

Sqoop komutunu çalıştırdıktan sonra hdfs dfs -ls -ls komutunu çalıştırarak varsayılan olarak tablo ismi ile oluşturulan dizini HDFS üzerinde görebiliriz.

 [hdfs@localhost:/sqoop]$ hdfs dfs -ls Found 1 items drwxrwxrwx - toptal data 0 2016-10-02 18:59 sales [hdfs@localhost:/sqoop]$

sales dizininin içeriğini listelemek için hdfs dfs -ls komutunu tekrar kullanabiliriz. HDFS'ye bakarsanız, verilerin yalnızca bir dosyada değil, varsayılan olarak dört dosyaya bölündüğünü ve dağıtıldığını fark edebilirsiniz.

 [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]$

hdfs dfs -cat komutu, satış verilerinin ilk bölümündeki tüm kayıtları HDFS'de görüntüler.

 [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]$

Varsayılan dosya sınırlayıcısının virgül olduğuna dikkat edin. Ayrıca, kaynaktaki 20 satır dört bölüme eşit olarak dağıtıldığından, her bölümde yalnızca beş satır olduğuna dikkat edin.

Ekrana çıkan satır sayısını sınırlamak için, cat komutunun çıktısını, diğer üç bölümün içeriğini kontrol etmek için aşağıda gösterildiği gibi head komutuna aktarabiliriz.

head komutunun -n 5 argümanı, ekran çıktısını ilk beş satırla sınırlar.

(Bizim durumumuzda, başlangıçta her bölümde yalnızca beş satır olduğundan bunun gereksiz olduğunu unutmayın. Ancak pratikte, muhtemelen her bölümde bundan çok daha fazla satırınız olacak ve yalnızca ilk birkaç satırı kontrol etmek isteyeceksiniz. doğru göründüklerinden emin olun, bu size nasıl yapılacağını gösterir.)

 [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]$

PostgreSQL veritabanındaki birden çok tablodan veri çıkarmak için bir sorgu çalıştırmanız gerekiyorsa, bu aşağıdaki komutla gerçekleştirilebilir:

 [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]$

Yukarıdaki komutta, Sqoop komutu için aynı argümanlardan bazılarını kullanıyoruz, ancak bir SQL komutuyla kullanıldığında farklı önemler alıyorlar.

  • --target-dir - Hedef dizin, Sqoop'a seçilen verileri HDFS'deki hangi dizinde depolayacağını söyler. Bu bağımsız değişken, serbest biçimli bir sorgu kullanılırken Sqoop tarafından gereklidir.
  • --split-by - Satış tablosunun birincil anahtarını seçmemize rağmen, iş yükünü dağıtmasına yardımcı olmak için Sqoop'a benzersiz bir tanımlayıcı sağlamamız gerekiyor.
  • --query - Bu, SQL sorgusunu sağladığımız argümandır. Yukarıdaki sorgu çift tırnak içine alınmıştır. Sorguyu içeren birden çok satırda ters eğik çizgi (satır devam karakteri) olmadığına dikkat edin. Ayrıca WHERE yan tümcesinin sonundaki and \$CONDITIONS dikkat edin. Bu, Sqoop tarafından gereklidir, çünkü Sqoop otomatik olarak $CONDITIONS belirtecini benzersiz bir ifadeyle değiştirecektir.

Sorunlar veya Sorun Yok: HDFS'yi Düşünmelisiniz

HDFS'nin ilişkisel veritabanlarına göre birçok avantajı vardır. Veri analizi yapıyorsanız, bugün verilerinizi HDFS'ye taşımayı düşünmelisiniz.

Burada öğrenilen becerilerle, ilişkisel bir veritabanı sisteminden verileri HDFS'ye aktarmak, tek bir komutla gerçekleştirilebilecek basit ve anlaşılır bir işlemdir. Bu örnekler az sayıda satıra sahip olsa da, büyük hacimli verileri bir PostgreSQL veritabanı tablosundan HDFS'ye aktarmanın mekanikleri aynı kalır.

Hatta büyük tabloları ve değişen depolama sınırlayıcılarını içe aktarmayı deneyebilirsiniz. Apache Sqoop kullanmak, veritabanı verilerini bir dosyaya aktarmaktan, dosyayı veritabanı sunucusundan HDFS'ye aktarmaktan ve ardından dosyayı HDFS'ye yüklemekten daha verimlidir.

İlgili: Verilerinizi R ile Arttırın