برنامج تعليمي HDFS لمحللي البيانات عالقون مع قواعد البيانات العلائقية
نشرت: 2022-03-11مقدمة
حتى الآن ، ربما تكون قد سمعت عن نظام الملفات الموزعة Hadoop (HDFS) ، خاصةً إذا كنت محلل بيانات أو شخصًا مسؤولاً عن نقل البيانات من نظام إلى آخر. ومع ذلك ، ما هي الفوائد التي يتمتع بها HDFS على قواعد البيانات العلائقية؟
HDFS هو حل قابل للتطوير ومفتوح المصدر لتخزين ومعالجة كميات كبيرة من البيانات. لقد ثبت أن HDFS موثوقة وفعالة عبر العديد من مراكز البيانات الحديثة.
يستخدم HDFS أجهزة سلعة جنبًا إلى جنب مع برامج مفتوحة المصدر لتقليل التكلفة الإجمالية لكل بايت من التخزين.
يعد HDFS نظامًا مثاليًا لتخزين البيانات ومعالجتها من أجل التحليلات ، وذلك بفضل النسخ المتماثل المدمج والمرونة لأعطال القرص. لا يتطلب الأسس والنفقات العامة لدعم ذرية المعاملات والاتساق والعزل والمتانة (ACID) كما هو ضروري مع أنظمة قواعد البيانات العلائقية التقليدية.
علاوة على ذلك ، عند مقارنتها بقواعد البيانات المؤسسية والتجارية ، مثل Oracle ، فإن استخدام Hadoop كنظام أساسي للتحليلات يتجنب أي تكاليف ترخيص إضافية.
أحد الأسئلة التي يطرحها الكثير من الناس عند التعرف على HDFS لأول مرة هو: كيف يمكنني الحصول على بياناتي الحالية في HDFS؟
في هذه المقالة ، سوف ندرس كيفية استيراد البيانات من قاعدة بيانات PostgreSQL إلى HDFS. سنستخدم Apache Sqoop ، وهو حاليًا الحل الأكثر فعالية ومفتوح المصدر لنقل البيانات بين HDFS وأنظمة قواعد البيانات العلائقية. تم تصميم Apache Sqoop لتحميل البيانات بشكل مجمّع من قاعدة بيانات علائقية إلى HDFS (استيراد) وكتابة البيانات بشكل مجمّع من HDFS إلى قاعدة بيانات علائقية (تصدير).
تمت كتابة الخطوات في هذا البرنامج التعليمي لشخص لديه معرفة أساسية بتنفيذ استعلامات SQL ومعرفة أولية بأوامر HDFS.
نظام قاعدة البيانات المستخدم هو PostgreSQL 9.5 لنظام التشغيل Windows ، وإصدار HDFS هو Cloudera Hadoop 2.5.0-cdh5.2.0 على جهاز ظاهري Centos 6.4 Linux.
يعتمد Apache Sqoop على ملفات JAR لبرنامج تشغيل JDBC الخاصة ببائع قاعدة البيانات العلائقية وإصدار قاعدة البيانات.
لتنفيذ الخطوات الموضحة في هذه المقالة ، سيحتاج المستخدم إلى أذونات للاتصال عن بُعد بقاعدة بيانات PostgreSQL ، وأذونات SELECT في قاعدة البيانات العلائقية ، وكتابة الأذونات على HDFS ، وتنفيذ الأذونات على Sqoop القابل للتنفيذ.
لغرض هذا البرنامج التعليمي ، أنشأنا قاعدة بيانات PostgreSQL ، وأطلقنا عليها اسم Toptal ، وجعلنا الوصول إليها ممكنًا من خلال المنفذ 5432.
مصدر بيانات PostgreSQL
للبدء ، في قاعدة بيانات PostgreSQL Toptal بنا ، سننشئ جدول بيانات اختبارًا باسم sales . سنفترض أن شهادة OpenSSL وملفات المفتاح الخاص موجودة بالفعل على خادم 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بعد ذلك ، سنقوم بإدراج 20 صفًا في الجدول:
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دعنا نختار البيانات للتحقق من صحة البيانات:
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)تبدو البيانات جيدة ، فلنتابع.
الاستيراد إلى HDFS باستخدام Sqoop
مع تحديد مصدر البيانات ، نحن الآن جاهزون لاستيراد البيانات إلى HDFS. يتم سرد الأمر sqoop الذي سنقوم بفحصه أدناه ، وسنقوم بتفصيل كل وسيطة في النقاط التالية. لاحظ أنه من المفترض أن يكون الأمر في سطر واحد كامل أو ، كما هو موضح أدناه ، بخط مائل عكسي (حرف متابعة سطر أوامر Linux) في نهاية كل سطر باستثناء الأخير.
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- يُطلق على الملف التنفيذي اسمsqoop، ونحن نوجهه لاستيراد البيانات من جدول أو عرض من قاعدة بيانات إلى HDFS. -
--connect- باستخدام الوسيطة--connect، نقوم بتمرير سلسلة JDBC connect الخاصة بـ PostgreSQL. في هذه الحالة ، نستخدم عنوان IP ورقم المنفذ واسم قاعدة البيانات. نحتاج أيضًا إلى تحديد أن SSL قيد الاستخدام ونحتاج إلى توفير فئةSSLSocketFactoryلاستخدامها. - - اسم
--username- في هذا المثال ، اسم المستخدم هو تسجيل دخول إلى PostgreSQL ، وليس تسجيل دخول إلى Windows. يجب أن يكون لدى المستخدم أذونات للاتصال بقاعدة البيانات المحددة والاختيار من الجدول المحدد. -
-P- سيؤدي هذا إلى مطالبة مستخدم سطر الأوامر بكلمة المرور. إذا تم تنفيذ Sqoop نادرًا ، فقد يكون هذا خيارًا جيدًا. هناك عدة طرق أخرى لتمرير كلمة المرور إلى الأمر تلقائيًا ، لكننا نحاول أن نجعلها بسيطة لهذه المقالة. -
--table- هذا هو المكان الذي نمرر فيه اسم جدول PostgreSQL. -
--target-dir- تحدد هذه الوسيطة دليل HDFS حيث سيتم تخزين البيانات. -
--split-by- يجب علينا تزويد Sqoop بمعرف فريد لمساعدته على توزيع عبء العمل. لاحقًا في إخراج الوظيفة ، سنرى أين يحدد Sqoop القيم الدنيا والقصوى للمساعدة في تعيين حدود الانقسام.
من المستحسن وضع الأمر في نص برمجي لأغراض التكرار والتحرير ، كما هو موضح أدناه:
[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]$الآن ، حان الوقت لتنفيذ البرنامج النصي لأمر Sqoop أعلاه. يتم عرض الإخراج من الأمر Sqoop أدناه.
[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]$لاحظ أن السطر الأخير من المخرجات أعلاه يوضح أنه تم استرداد 20 سجلًا ، وهو ما يتوافق مع 20 سجلًا في الجدول في قاعدة بيانات PostgreSQL.

بعد تنفيذ الأمر Sqoop ، يمكننا تنفيذ الأمر hdfs dfs -ls لرؤية الدليل الذي تم إنشاؤه افتراضيًا باسم الجدول على HDFS.
[hdfs@localhost:/sqoop]$ hdfs dfs -ls Found 1 items drwxrwxrwx - toptal data 0 2016-10-02 18:59 sales [hdfs@localhost:/sqoop]$ يمكننا استخدام الأمر hdfs dfs -ls مرة أخرى لسرد محتويات دليل sales . إذا نظرت إلى HDFS ، يمكنك ملاحظة أن البيانات مقسمة وموزعة عبر أربعة ملفات بشكل افتراضي ، وليس فقط في ملف واحد.
[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 جميع السجلات في القسم الأول من بيانات المبيعات على 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]$لاحظ أن محدد الملف الافتراضي هو فاصلة. لاحظ أيضًا أنه لا يوجد سوى خمسة صفوف في كل قسم ، لأنه تم توزيع 20 صفاً في المصدر بالتساوي عبر الأقسام الأربعة.
للحد من عدد الصفوف التي يتم إخراجها على الشاشة ، يمكننا توجيه إخراج الأمر cat إلى الأمر head كما هو موضح أدناه ، للتحقق من محتويات الأقسام الثلاثة الأخرى.
تحدد الوسيطة -n 5 للأمر head إخراج الشاشة إلى الصفوف الخمسة الأولى.
(لاحظ أنه في حالتنا ، هذا غير ضروري نظرًا لوجود خمسة صفوف فقط في كل قسم لتبدأ به. ولكن من الناحية العملية ، من المحتمل أن يكون لديك العديد من الصفوف أكثر من هذا في كل قسم وستريد فقط التحقق من أول بضعة صفوف من أجل تأكد من أنها تبدو صحيحة ، وهذا يوضح لك كيفية القيام بذلك.)
[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 ، فيمكن تحقيق ذلك باستخدام الأمر التالي:
[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]$في الأمر أعلاه ، نستخدم بعض الحجج نفسها لأمر Sqoop ، لكنها تأخذ أهمية مختلفة عند استخدامها مع أمر SQL.
-
--target-dir- يخبر الدليل الهدف Sqoop في أي دليل على HDFS لتخزين البيانات المحددة. هذه الوسيطة مطلوبة من قبل Sqoop عند استخدام استعلام حر. -
--split-by- على الرغم من أننا نختار المفتاح الأساسي لجدول المبيعات ، فلا يزال يتعين علينا تزويد Sqoop بمعرف فريد لمساعدته في توزيع عبء العمل. -
--query- هذه هي الحجة التي نقدم فيها استعلام SQL. الاستعلام أعلاه محاط بعلامات اقتباس مزدوجة. لاحظ عدم وجود شرطة مائلة للخلف (حرف متابعة السطر) في الأسطر المتعددة التي تحتوي على الاستعلام. لاحظ أيضًاand \$CONDITIONSفي نهايةWHERE. هذا مطلوب بواسطة Sqoop لأن Sqoop سيحل تلقائيًا محل الرمز المميز$CONDITIONSبتعبير فريد.
مشاكل أو لا مشاكل: يجب أن تفكر في HDFS
تتمتع HDFS بالعديد من المزايا مقارنة بقواعد البيانات العلائقية. إذا كنت تقوم بتحليل البيانات ، فيجب أن تفكر في ترحيل بياناتك إلى HDFS ، اليوم.
من خلال المهارات المكتسبة هنا ، يعد استيراد البيانات من نظام قاعدة بيانات علائقية إلى HDFS عملية بسيطة ومباشرة يمكن إنجازها باستخدام أمر واحد. بينما تحتوي هذه الأمثلة على عدد قليل من الصفوف ، تظل آليات استيراد كميات كبيرة من البيانات إلى HDFS من جدول قاعدة بيانات PostgreSQL كما هي.
يمكنك حتى تجربة استيراد جداول كبيرة ومحددات تخزين مختلفة. يعد استخدام Apache Sqoop أكثر كفاءة من تصدير بيانات قاعدة البيانات إلى ملف ، ونقل الملف من خادم قاعدة البيانات إلى HDFS ، ثم تحميل الملف إلى HDFS.
