وظائف هايف: مثال على الوظائف المدمجة والوظائف المعرفة من قبل المستخدم

⚡ ملخص ذكي

تنقسم وظائف Hive إلى مجموعتين: وظائف مدمجة تأتي مع المحرك وتغطي مهام التجميع والتاريخ والعمليات الحسابية والشرطية والسلاسل النصية وغيرها، ووظائف معرفة من قبل المستخدم مكتوبة بلغة برمجة أخرى. Java بالنسبة للمنطق الذي لا يوفره Hive.

  • 📚 ست عائلات مدمجة: يمكن استدعاء وظائف المجموعات والتواريخ والرياضيات والشروط والسلاسل والوظائف المتنوعة مباشرة داخل HiveQL.
  • 🧾 التوقيعات مهمة: لكل دالة قائمة وسائط ثابتة ونوع إرجاع موثق، لذا فإن نوع الإرجاع هو الذي يحدد مكان استخدامها.
  • 🧩 تقوم دالة المستخدم (UDF) بسد الثغرات: عندما لا توجد وظيفة مدمجة، أ Java توفر الفئة التي تمتد من org.apache.hadoop.hive.ql.exec.UDF العملية المفقودة.
  • 🔢 ثلاثة أشكال للوظائف المخصصة: تقوم الدالة المعرفة من قبل المستخدم (UDF) بإرجاع صف واحد لكل صف، وتقوم الدالة المعرفة من قبل المستخدم (UDAF) بدمج العديد من الصفوف في صف واحد، وتقوم الدالة المعرفة من قبل المستخدم (UDTF) بتوسيع صف واحد إلى عدة صفوف.
  • 🛠️ التسجيل على خطوتين: يقوم الأمر ADD JAR بوضع الكود في مسار الفئة، بينما يقوم الأمر CREATE TEMPORARY FUNCTION بربط اسم بالفئة.
  • ♻️ إعادة الاستخدام هي الهدف: يمكن استدعاء دالة معرفة من قبل المستخدم تم اختبارها، مثل دالة تجذير الكلمات، من كل استعلام بدلاً من إعادة كتابتها في كل مرة.

وظائف هايف: الوظائف المدمجة والوظائف التي يُعرّفها المستخدم

تم تصميم الدوال لغرض محدد لإجراء عمليات مثل العمليات الرياضية والحسابية والمنطقية والعلائقية على معاملات أسماء أعمدة الجدول.

وظائف مدمجة

هذه هي الوظائف المتوفرة بالفعل في الخلية. أولاً، علينا التحقق من متطلبات التطبيق، وبعد ذلك يمكننا استخدام هذه الوظائف المضمنة في تطبيقاتنا. يمكننا استدعاء هذه الوظائف مباشرة في تطبيقنا.

سيتم ذكر بناء الجملة والأنواع في القسم التالي.

أنواع الوظائف المدمجة في Hive:

  • وظائف التجميع
  • وظائف التاريخ
  • وظائف رياضية
  • الوظائف الشرطية
  • وظائف السلسلة
  • متنوعات. المهام

يتم تغطية كل عائلة من العائلات الست أدناه مع توقيعات وظائفها وأنواع الإرجاع الخاصة بها.

وظائف التجميع

تُستخدم هذه الدوال للمجموعات. المجموعات تعني المجموعةping من العناصر، وتعيد عنصرًا واحدًا أو مصفوفة من العناصر اعتمادًا على نوع الإرجاع المذكور في اسم الدالة.

نوع الإرجاع اسم الوظيفة الوصف
INT الحجم (الخريطة ) سيقوم بجلب عدد المكونات في نوع الخريطة وإعطائها
INT الحجم (صفيف ) سيقوم بجلب عدد العناصر في نوع المصفوفة وإعطائه
مجموعة مصفوفة map_keys(Map ) سيقوم بجلب مصفوفة تحتوي على مفاتيح خريطة الإدخال وإعطائها. المصفوفة غير مرتبة.
مجموعة مصفوفة map_values(Map ) سيقوم البرنامج بجلب مصفوفة تحتوي على قيم خريطة الإدخال وإعادتها. المصفوفة غير مرتبة.
المصفوفة فرز_المصفوفة(المصفوفة) ) يقوم بترتيب مصفوفة الإدخال ترتيبًا تصاعديًا لعناصرها ثم يعيدها
منطقية array_contains(Array ، قيمة) تُرجع الدالة القيمة TRUE إذا كانت المصفوفة تحتوي على القيمة المُمررة كوسيط ثانٍ

وظائف التاريخ

تُستخدم هذه الأدوات لإجراء عمليات معالجة التواريخ وتحويل أنواع التواريخ من نوع إلى آخر:

اسم الوظيفة نوع الإرجاع الوصف
unix_timestamp() BIGINT سنحصل على التيار يونكس الطابع الزمني بالثواني. القيمة ليست ثابتة للاستعلام بأكمله.
to_date(string timestamp) تاريخ سيقوم بجلب جزء التاريخ من سلسلة الطابع الزمني وإعطائه
السنة (تاريخ السلسلة) INT سيتم جلب وإعطاء السنة جزء من التاريخ أو سلسلة الطابع الزمني
الربع (التاريخ/الطابع الزمني/السلسلة) INT سيتم جلب ربع العام وإعطاءه لتاريخ أو طابع زمني أو سلسلة في النطاق من 1 إلى 4
شهر (تاريخ السلسلة) INT سيعطي جزء الشهر من التاريخ أو سلسلة الطابع الزمني
ساعة (تاريخ السلسلة) INT سيقوم بجلب وعرض ساعة الطابع الزمني
دقيقة (تاريخ السلسلة) INT سيقوم بجلب وعرض دقيقة الطابع الزمني
date_sub(string starting date, int days) تاريخ سيجلب ويعطي نتيجة العملية الفرعيةtracبعد عدد من الأيام من تاريخ البدء
التاريخ الحالي تاريخ سيقوم بجلب التاريخ الحالي وعرضه في بداية تقييم الاستعلام.
last_day(string date) سلسلة سيجلب ويعطي آخر يوم من الشهر الذي ينتمي إليه التاريخ
Trunc (تاريخ السلسلة، تنسيق السلسلة) سلسلة سيقوم بجلب التاريخ وإعطائه مختصراً إلى الوحدة المحددة بواسطة التنسيق. أشكال الدعم: شهر/إثنين/شهر، سنة/YYYY/YY.

وظائف رياضية

تُستخدم هذه الدوال لإجراء العمليات الحسابية. وبدلاً من إنشاء دوال معرفة من قبل المستخدم، لدينا بعض الدوال الرياضية المدمجة في Hive.

اسم الوظيفة نوع الإرجاع الوصف
جولة (X مزدوجة) DOUBLE سيقوم بجلب وإرجاع قيمة BIGINT المقربة لـ X
جولة (X مزدوجة، INT d) DOUBLE سيجلب ويعيد قيمة X مقربة إلى d منزلة عشرية
مُحاط(علامة X مزدوجة) DOUBLE سيقوم البرنامج بجلب وإرجاع قيمة BIGINT المقربة لـ X باستخدام وضع التقريب HALF_EVEN، المعروف أيضًا باسم تقريب المصرفيين.
الأرضية (مزدوجة X) كبير سيقوم بجلب وإرجاع أكبر قيمة من نوع BIGINT تساوي أو تقل عن قيمة X
سقف (مزدوج أ)، سقف (مزدوج أ) كبير سيقوم بجلب وإرجاع أصغر قيمة BIGINT تساوي أو تزيد عن قيمة a
راند ()، راند (بذور INT) DOUBLE سيقوم البرنامج بجلب وإرجاع رقم عشوائي موزع توزيعًا منتظمًا بين 0 و1. تحديد قيمة ابتدائية يجعل التسلسل قابلاً للتكرار.

الوظائف الشرطية

تُستخدم هذه الدوال لإجراء عمليات التحقق من القيم الشرطية.

اسم الوظيفة نوع الإرجاع الوصف
إذا (اختبار منطقي، T valueTrue، T valueFalseOrNull) T سيعطي قيمة صحيحة عندما يكون شرط الاختبار صحيحًا، وقيمة خاطئة أو فارغة في غير ذلك.
isnull(X) منطقية سيقوم بجلب القيمة وإعطائها القيمة "صحيح" إذا كانت X تساوي NULL، و"خطأ" في غير ذلك.
isnotnull(X) منطقية سيقوم بجلب القيمة وإعطائها القيمة "صحيح" إذا لم تكن X فارغة، و"خطأ" في غير ذلك.
nvl(T value, T default_value) T سيعطي القيمة الافتراضية عندما تكون القيمة فارغة، والقيمة في غير ذلك.

وظائف السلسلة

تتم معالجة عمليات التلاعب بالسلاسل النصية وعملياتها بواسطة الوظائف التالية.

اسم الوظيفة نوع الإرجاع الوصف
عكس (السلسلة X) سلسلة سوف يعطي السلسلة المعكوسة من X
rpad (سلسلة str، طول int، لوحة السلسلة) سلسلة سيقوم بجلب وإعطاء str مع إضافة حشو إلى اليمين حتى يصل الطول الإجمالي إلى طول
rtrim(string X) سلسلة سيقوم بجلب وإرجاع السلسلة الناتجة عن إزالة المسافات من نهاية (الجانب الأيمن) X.
مثلا، يؤدي rtrim('النتائج') إلى 'النتائج'
الفضاء (INT ن) سلسلة سيقوم بجلب وإعطاء سلسلة من n مسافة.
انقسام (STRING str، STRING بات) مجموعة ينقسم str حول pat (pat هو تعبير عادي).
str_to_map(text[, delimiter1, delimiter2]) رسم خريطة سيقوم البرنامج بتقسيم النص إلى أزواج مفتاح-قيمة باستخدام فاصلين. يفصل الفاصل الأول الأزواج، بينما يقسم الفاصل الثاني كل زوج على حدة.

متنوعات. المهام

تتضمن العديد من الوظائف المدمجة وظائف لا تنتمي إلى أي من العائلات المذكورة أعلاه. وتشمل هذه الوظائف التجزئة، ومعلومات الجلسة، واستدعاء الدوال العشوائية. Java الأساليب.

اسم الوظيفة نوع الإرجاع الوصف
hash(a1[, a2…]) INT تُعيد هذه الدالة قيمة تجزئة للوسائط المُدخلة.
المستخدم الحالي() سلسلة يُعيد اسم المستخدم الحالي من مدير المصادقة المُكوّن
current_database() سلسلة يُعيد اسم قاعدة البيانات الحالية
md5(سلسلة نصية/ثنائية) سلسلة تُعيد هذه الدالة مجموع التحقق MD5 ذي 128 بت كسلسلة من 32 رقمًا سداسيًا عشريًا، أو قيمة NULL في حالة إدخال وسيط NULL.
sha1(سلسلة/ثنائي) سلسلة يُعيد هذا الكود ملخص SHA-1 للوسيط كسلسلة سداسية عشرية.
crc32(سلسلة/ثنائي) BIGINT تُعيد هذه الدالة قيمة فحص التكرار الدوري لوسيط نصي أو ثنائي.
إصدار() سلسلة يُعيد إصدار Hive كرقم بناء متبوعًا برمز تجزئة البناء
reflect(class, method[, arg1…]) يختلف يُطلق عليه اسم Java يتم تعريف الدالة عن طريق مطابقة توقيع الوسيط، باستخدام الانعكاس. java_method() مرادف لها.

UDFs (الوظائف المحددة من قبل المستخدم)

في Hive، يمكن للمستخدمين تعريف وظائفهم الخاصة لتلبية متطلبات عملاء محددة. تُعرف هذه الوظائف باسم UDFs في Hive. تُكتب الوظائف المُعرّفة من قِبل المستخدم بلغة برمجة معينة. Java لوحدات محددة.

تم تصميم بعض الدوال المعرفة من قبل المستخدم (UDFs) خصيصًا لإعادة استخدام التعليمات البرمجية في أطر عمل التطبيقات. يكتب المطور هذه الدوال في Java ويقوم بدمج تلك الدوال المعرفة من قبل المستخدم مع Hive.

أثناء تنفيذ الاستعلام، يمكن للمطور استخدام الكود مباشرةً، وستُعيد الدوال المعرفة من قِبل المستخدم (UDFs) المخرجات وفقًا للمهام المُحددة من قِبل المستخدم. يوفر ذلك أداءً عاليًا من حيث كتابة الكود وتنفيذه.

على سبيل المثال، لا توجد لدينا أي دالة مُعرّفة مسبقًا في Hive لاستخراج جذور السلاسل النصية. ولذلك، يمكننا كتابة دالة معرفة من قبل المستخدم (UDF) لاستخراج الجذور في Javaأينما احتجنا إلى وظائف الجذر، يمكننا استدعاء دالة تعريف المستخدم (UDF) الخاصة بالجذر مباشرةً في Hive.

هنا، تعني وظيفة التجريد اشتقاق الكلمات من جذورها. تقوم خوارزمية التجريد باختزال الكلمات "wishing" و"wished" و"wishes" إلى الكلمة الجذرية "wish". ولتنفيذ هذا النوع من الوظائف، يمكننا كتابة دالة معرفة من قبل المستخدم (UDF) بلغة البرمجة التالية: Java ودمجها معها خلية النحل.

اعتمادًا على حالة الاستخدام، يمكن كتابة دالة المستخدم (UDF) لقبول وإنتاج أعداد مختلفة من قيم الإدخال والإخراج.

يقبل النوع العام من الدوال المعرفة من قبل المستخدم قيمة إدخال واحدة وينتج قيمة إخراج واحدة. إذا تم استخدام هذه الدالة في استعلام، فسيتم استدعاؤها مرة واحدة لكل صف في مجموعة بيانات النتائج.

في المقابل، يمكن للدالة أن تقبل مجموعة من القيم كمدخلات وأن تُرجع قيمة واحدة كمخرجات. هذا الاختلاف هو ما يميز أنواع الدوال المخصصة الثلاثة الموضحة لاحقًا.

مقارنة بين UDF و UDAF و UDTF في Hive

تُصنّف الدوال المخصصة في Hive حسب عدد الصفوف المُدخلة والمُخرجة. ويُعدّ اختيار النوع الخاطئ السبب الأكثر شيوعًا لرفض الدالة المخصصة التجميع أو إرجاعها صفًا واحدًا بدلًا من جدول.

النوع صفوف للداخل → صفوف للخارج فئة للتوسع أمثلة مضمنة
UDF صف واحد → صف واحد org.apache.hadoop.hive.ql.exec.UDF دالة الطول، دالة التقريب، دالة العكس
UDAF صفوف متعددة → صف واحد org.apache.hadoop.hive.ql.udf.generic.Abstracمحلل UDAF العام count(), min(), max()
UDTF صف واحد → صفوف متعددة org.apache.hadoop.hive.ql.udf.generic.GenericUDTF explode()، json_tuple()، parse_url_tuple()

ينتج عن الجدول قاعدتان عمليتان:

  • يتم عادةً إقران UDAF بعبارة GROUP BY، لأنها تقوم بدمج كل مجموعة في صف واحد.
  • لا يمكن تحديد UDTF جنبًا إلى جنب مع الأعمدة الأخرى في نفس قائمة SELECT، لذلك يتم استخدامه عادةً مع LATERAL VIEW.

يوجد أيضًا فئة أساسية ثانية أكثر قدرة للعمل على مستوى الصف، وهي GenericUDF، والتي تقبل أنواعًا معقدة مثل المصفوفات والخرائط والهياكل وعددًا متغيرًا من الوسائط.

كيفية كتابة وتسجيل دالة معرفة من قبل المستخدم في هايف

يمكن بناء مثال الجذع الموصوف أعلاه كدالة حقيقية في أربع خطوات. لا شيء يتجاوز ذلك Java يلزم وجود برنامج تجميع وجلسة Hive قيد التشغيل.

الخطوة 1) اكتب Java فئة ترث من فئة UDF وتُنفذ دالة evaluate() العامة. يستدعي Hive الدالة evaluate() مرة واحدة لكل صف، لذا يجب أن تتعامل الدالة مع قيمة NULL المدخلة.

package com.guru99.hive.udf;

import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;

public final class Stem extends UDF {

    public Text evaluate(final Text input) {
        if (input == null) {
            return null;
        }
        String word = input.toString().toLowerCase();
        if (word.endsWith("ing")) {
            word = word.substring(0, word.length() - 3);
        } else if (word.endsWith("ed") || word.endsWith("es")) {
            word = word.substring(0, word.length() - 2);
        }
        return new Text(word);
    }
}

الخطوة 2) قم بتجميع الفئة وتغليفها في ملف JAR، على سبيل المثال hive-udf-1.0.jar، مع أي فئات تعتمد عليها.

الخطوة 3) ضع ملف JAR في مسار فئة Hive واربط اسم دالة بالفئة. الدالة المؤقتة تعمل فقط خلال الجلسة الحالية.

ADD JAR /home/hduser/hive-udf-1.0.jar;

CREATE TEMPORARY FUNCTION stem AS 'com.guru99.hive.udf.Stem';

الخطوة 4) استدعِ الدالة الجديدة تمامًا كما تستدعي الدالة المدمجة. عند تطبيقها على الكلمات "wishing" و"wished" و"wishes"، تُرجع هذه الفئة "wish" للكلمات الثلاث.

SELECT word, stem(word) FROM words;

لضمان توفر هذه الوظيفة لكل جلسة ولكل مستخدم، قم بتسجيلها بشكل دائم في قاعدة بيانات. يجب أن يكون ملف JAR موجودًا على مسار يمكن للمجموعة بأكملها قراءته، وهو ما يعني عادةً نظام ملفات Hadoop الموزع (HDFS).

CREATE FUNCTION default.stem AS 'com.guru99.hive.udf.Stem'
USING JAR '/user/hive/udfs/hive-udf-1.0.jar';

يمكن لفئة واحدة أن تُعلن عن أكثر من دالة evaluate(). يقوم Hive بمطابقة استدعاء الدالة مع توقيعات الوسائط، وهذا ما يسمح لدالة واحدة بقبول كل من سلسلة نصية وعدد صحيح.

الأسئلة الشائعة

يعرض الأمر SHOW FUNCTIONS جميع الأسماء المسجلة، بما في ذلك الأسماء المخصصة. ويطبع الأمر DESCRIBE FUNCTION name توقيعًا من سطر واحد، بينما يضيف الأمر DESCRIBE FUNCTION EXTENDED name أمثلة على الاستخدام حيثما توفرها الفئة المنفذة.

غالباً ما تكون المشكلة متعلقة بالاسم أو النطاق: يجب أن يكون النص الذي يلي AS هو اسم الفئة المؤهل بالكامل، ولا ينطبق الأمر ADD JAR إلا على الجلسة التي شغّلته. يؤدي إعادة الاتصال إلى حذف كل من ملف JAR وأي دالة مؤقتة.

استخدم GenericUDF عندما تأخذ الدالة أنواعًا معقدة مثل المصفوفات أو الخرائط أو الهياكل، أو عددًا متغيرًا من الوسائط، أو عندما تحتاج إلى التحقق من صحة أنواع الوسائط بنفسها. أما فئة UDF البسيطة فتحل الأنواع باستخدام الانعكاس وتتعامل فقط مع أنواع البيانات الأولية القابلة للكتابة.

يجب أن تعمل دالة المستخدم الحقيقية على جهاز جافا الافتراضي (JVM). أما بالنسبة للغات الأخرى، خلية النحل يوفر هذا الخيار عبارة TRANSFORM، التي تقوم بتمرير كل صف عبر نص برمجي خارجي مثل Python عبر المدخلات والمخرجات القياسية. إنه أبطأ ولكنه يتجنب Java تماما.

يمكنهم ذلك. تُنفَّذ الدالة evaluate() مرة واحدة لكل صف، مما يؤدي إلى مضاعفة العمليات الحسابية المكلفة بعدد الصفوف، كما أن تخصيص الكائنات داخل الدالة يزيد من ضغط جمع البيانات المهملة. يُفضَّل استخدام دالة مُدمجة عند وجودها، ويجب إبقاء الدالة evaluate() خالية من عمليات الإدخال/الإخراج.

لا. يتم حل أسماء الدوال بغض النظر عن حالة الأحرف، لذا فإن ROUND() و Round() و round() هي نفس الدالة. Java اسم الفئة في عبارة AS هو أمر مختلف ويجب أن يتطابق تمامًا مع الفئة المترجمة، بما في ذلك حزمتها.

تقوم أدوات التعلم الآلي بربط وصف بلغة بسيطة بالتوقيعات المرشحة، وتحذر عندما لا يتناسب نوع الإرجاع مع العمود المستهدف. تحقق من الاقتراح مقابل التوقيع الموثق، لأن الأسماء المُولّدة قد تنتمي أحيانًا إلى لهجة SQL أخرى.

يُنتج هذا البرنامج هيكلاً قابلاً للاستخدام - يشمل تعريف الفئة، وعناصر الاستيراد، ودالة evaluate() - انطلاقاً من تعليق يصف العملية. لا تزال معالجة القيم الفارغة، وأنواع البيانات القابلة للكتابة، وخطوة التغليف بحاجة إلى مراجعة، ويجب اختبار الدالة على صفوف بيانات حقيقية.

تلخيص هذه التدوينة بـ: