ฟังก์ชัน Hive: ฟังก์ชันในตัวและฟังก์ชันที่ผู้ใช้กำหนดเอง (UDF) ตัวอย่าง
⚡ สรุปอย่างชาญฉลาด
ฟังก์ชันของ Hive แบ่งออกเป็นสองกลุ่ม: ฟังก์ชันสำเร็จรูปที่มาพร้อมกับระบบ ซึ่งครอบคลุมงานด้านการรวบรวม วันที่ คณิตศาสตร์ เงื่อนไข สตริง และงานอื่นๆ และฟังก์ชันที่ผู้ใช้กำหนดเอง Java Hive ไม่ได้จัดหาตรรกะดังกล่าวให้

ฟังก์ชันถูกสร้างขึ้นเพื่อวัตถุประสงค์เฉพาะ เพื่อดำเนินการต่างๆ เช่น การคำนวณทางคณิตศาสตร์ เลขคณิต ตรรกะ และความสัมพันธ์ บนตัวถูกดำเนินการของชื่อคอลัมน์ในตาราง
ฟังก์ชั่นในตัว
เหล่านี้เป็นฟังก์ชันที่มีอยู่ใน Hive อยู่แล้ว ขั้นแรก เราต้องตรวจสอบข้อกำหนดของแอปพลิเคชัน จากนั้นเราจึงสามารถใช้ฟังก์ชันในตัวเหล่านี้ในแอปพลิเคชันของเราได้ เราสามารถเรียกใช้ฟังก์ชันเหล่านี้ได้โดยตรงในแอปพลิเคชันของเรา
มีการกล่าวถึงรูปแบบและประเภทต่างๆ ในส่วนต่อไปนี้
ประเภทของฟังก์ชันในตัวของ Hive:
- ฟังก์ชั่นการรวบรวม
- ฟังก์ชั่นวันที่
- ฟังก์ชันทางคณิตศาสตร์
- ฟังก์ชันแบบมีเงื่อนไข
- ฟังก์ชันสตริง
- อื่น ๆ. ฟังก์ชั่น
แต่ละตระกูลทั้งหกตระกูลจะได้รับการอธิบายโดยละเอียดด้านล่าง พร้อมทั้งรูปแบบการใช้งานและประเภทค่าส่งกลับ
ฟังก์ชั่นการรวบรวม
ฟังก์ชันเหล่านี้ใช้สำหรับคอลเลกชัน คอลเลกชันหมายถึงกลุ่มping ประกอบด้วยองค์ประกอบหลายรายการ และจะส่งคืนองค์ประกอบเดียวหรืออาร์เรย์ขององค์ประกอบ ขึ้นอยู่กับประเภทการส่งคืนที่ระบุไว้ในชื่อฟังก์ชัน
| ประเภทผลตอบแทน | ชื่อฟังก์ชั่น | Descriptไอออน |
|---|---|---|
| INT | ขนาด(แผนที่ - | ฟังก์ชันนี้จะดึงข้อมูลและแสดงจำนวนส่วนประกอบในประเภทแผนที่ |
| INT | ขนาด(อาร์เรย์ - | ฟังก์ชันนี้จะดึงข้อมูลและแสดงจำนวนองค์ประกอบในอาร์เรย์ประเภทนั้น |
| อาร์เรย์ | map_keys(แผนที่ ) | ฟังก์ชันนี้จะดึงข้อมูลและส่งคืนอาร์เรย์ที่มีคีย์ของแผนที่อินพุต อาร์เรย์นี้ไม่มีลำดับ |
| อาร์เรย์ | ค่าแผนที่ (แผนที่) ) | ฟังก์ชันนี้จะดึงข้อมูลและส่งคืนอาร์เรย์ที่มีค่าจากแผนที่อินพุต อาร์เรย์นี้ไม่มีลำดับ |
| อาร์เรย์ | เรียงลำดับอาร์เรย์ (อาร์เรย์) ) | เรียงลำดับอาร์เรย์อินพุตตามลำดับจากน้อยไปมากตามจำนวนองค์ประกอบ และส่งคืนค่าที่เรียงลำดับแล้ว |
| บูลีน | อาร์เรย์ประกอบด้วย (อาร์เรย์) , ค่า) | ส่งคืนค่า TRUE หากอาร์เรย์มีค่าที่ส่งมาเป็นอาร์กิวเมนต์ตัวที่สอง |
ฟังก์ชั่นวันที่
ฟังก์ชันเหล่านี้ใช้สำหรับจัดการข้อมูลวันที่และแปลงประเภทข้อมูลวันที่จากประเภทหนึ่งไปเป็นอีกประเภทหนึ่ง:
| ชื่อฟังก์ชั่น | ประเภทผลตอบแทน | Descriptไอออน |
|---|---|---|
| ยูนิกซ์_ไทม์สแตมป์() | bigint | เราจะได้รับกระแสไฟฟ้า ยูนิกซ์ เวลาในหน่วยวินาที ค่านี้ไม่คงที่ตลอดทั้งคำสั่งค้นหา |
| to_date(string timestamp) | ข้อมูล | ฟังก์ชันนี้จะดึงและแสดงส่วนวันที่ของสตริงไทม์สแตมป์ |
| ปี (วันที่สตริง) | INT | มันจะดึงข้อมูลและให้ส่วนปีของวันที่หรือสตริงการประทับเวลา |
| ไตรมาส (วันที่/เวลา/สตริง) | INT | มันจะดึงข้อมูลและให้ไตรมาสของปีเป็นวันที่ เวลาประทับ หรือสตริงในช่วง 1 ถึง 4 |
| เดือน (วันที่สตริง) | INT | จะให้ส่วนของเดือนของวันที่หรือสตริงการประทับเวลา |
| ชั่วโมง (วันที่สตริง) | INT | ระบบจะดึงข้อมูลและแสดงชั่วโมงของเวลาที่บันทึกไว้ |
| นาที (วันที่สตริง) | INT | ระบบจะดึงข้อมูลและแสดงนาทีของเวลาดังกล่าว |
| date_sub(string วันที่เริ่มต้น, จำนวนวัน) | ข้อมูล | ระบบจะดึงข้อมูลและแสดงผลลัพธ์ของคำสั่งย่อยtracนับจำนวนวันจากวันที่เริ่มต้น |
| วันที่ปัจจุบัน | ข้อมูล | ระบบจะดึงและแสดงวันที่ปัจจุบันเมื่อเริ่มต้นการประเมินคำสั่งค้นหา |
| วันสุดท้าย (สตริงวันที่) | เชือก | ระบบจะดึงข้อมูลและแสดงวันสุดท้ายของเดือนที่ตรงกับวันที่นั้น |
| trunc (วันที่สตริง รูปแบบสตริง) | เชือก | ระบบจะดึงข้อมูลและแสดงวันที่โดยตัดทอนให้เหลือเฉพาะหน่วยตามรูปแบบที่กำหนดไว้ รูปแบบที่รองรับ: เดือน/จันทร์/ดด ปี/ปปปป/ปป |
ฟังก์ชันทางคณิตศาสตร์
ฟังก์ชันเหล่านี้ใช้สำหรับการคำนวณทางคณิตศาสตร์ แทนที่จะสร้าง UDF (User-Defined Functions) เรามีฟังก์ชันทางคณิตศาสตร์ที่สร้างไว้แล้วใน Hive
| ชื่อฟังก์ชั่น | ประเภทผลตอบแทน | Descriptไอออน |
|---|---|---|
| รอบ(Xคู่) | ซ้อน | ฟังก์ชันนี้จะดึงและส่งคืนค่า BIGINT ที่ปัดเศษของ X |
| รอบ(DOUBLE X, INT d) | ซ้อน | ฟังก์ชันนี้จะดึงข้อมูลและส่งคืนค่า X ที่ปัดเศษเป็นทศนิยม d ตำแหน่ง |
| รอบ(ดับเบิลเอ็กซ์) | ซ้อน | ฟังก์ชันนี้จะดึงและส่งคืนค่า BIGINT ที่ปัดเศษแล้วของ X โดยใช้โหมดการปัดเศษแบบ HALF_EVEN หรือที่เรียกว่าการปัดเศษแบบธนาคาร |
| พื้น(ดับเบิลเอ็กซ์) | บิ๊กอินท์ | ฟังก์ชันนี้จะดึงและส่งคืนค่า BIGINT สูงสุดที่เท่ากับหรือน้อยกว่าค่า X |
| เพดาน(คู่ a), เพดาน(คู่ a) | บิ๊กอินท์ | ฟังก์ชันนี้จะดึงและส่งคืนค่า BIGINT ที่น้อยที่สุดซึ่งเท่ากับหรือมากกว่าค่า a |
| แรนด์ (), แรนด์ (เมล็ด INT) | ซ้อน | ฟังก์ชันนี้จะดึงและส่งคืนหมายเลขสุ่มที่มีการกระจายแบบสม่ำเสมอจาก 0 ถึง 1 การกำหนดค่าเริ่มต้น (seed) จะทำให้ลำดับหมายเลขนั้นซ้ำกันได้ |
ฟังก์ชันแบบมีเงื่อนไข
ฟังก์ชันเหล่านี้ใช้สำหรับการตรวจสอบค่าแบบมีเงื่อนไข
| ชื่อฟังก์ชั่น | ประเภทผลตอบแทน | Descriptไอออน |
|---|---|---|
| ถ้า (เงื่อนไขการทดสอบบูลีน, T valueTrue, T valueFalseOrNull) | T | ฟังก์ชันนี้จะให้ค่า valueTrue เมื่อ testCondition เป็นจริง และให้ค่า valueFalseOrNull ในกรณีอื่น ๆ |
| เป็นค่าว่าง (X) | บูลีน | ฟังก์ชันนี้จะดึงข้อมูลและส่งค่า true หาก X เป็น NULL และส่งค่า false ในกรณีอื่นๆ |
| ไม่เป็นค่าว่าง (X) | บูลีน | ฟังก์ชันนี้จะดึงข้อมูลและส่งค่า true หาก X ไม่ใช่ค่า NULL และส่งค่า false ในกรณีอื่นๆ |
| nvl(T value, T default_value) | T | ฟังก์ชันนี้จะกำหนดค่า default_value เมื่อค่า value เป็น NULL และกำหนดค่า value ในกรณีอื่นๆ |
ฟังก์ชันสตริง
การจัดการและการดำเนินการกับสตริงจะดำเนินการโดยฟังก์ชันต่อไปนี้
| ชื่อฟังก์ชั่น | ประเภทผลตอบแทน | Descriptไอออน |
|---|---|---|
| กลับด้าน(สตริง X) | เชือก | มันจะให้สตริงกลับด้านของ X |
| rpad(สตริง str, ความยาว int, แพดสตริง) | เชือก | มันจะดึงข้อมูลและส่งค่า str ที่เติมช่องว่างด้านขวาให้มีความยาวรวมเท่ากับความยาวที่กำหนด |
| rtrim(string X) | เชือก | ฟังก์ชันนี้จะดึงและส่งคืนสตริงที่ได้จากการตัดช่องว่างออกจากส่วนท้าย (ด้านขวา) ของตัวอักษร X ตัวอย่างเช่น, rtrim(' results ') ผลลัพธ์ใน ' results' |
| พื้นที่(INT n) | เชือก | ฟังก์ชันนี้จะดึงข้อมูลและแสดงผลเป็นสตริงที่มีช่องว่าง n ช่อง |
| แยก (STRING str, STRING ตบเบา ๆ ) | แถว | แยก str รอบ pat (pat เป็นนิพจน์ทั่วไป) |
| str_to_map(text[, delimiter1, delimiter2]) | แผนที่ | โปรแกรมจะแยกข้อความออกเป็นคู่คีย์-ค่าโดยใช้ตัวคั่นสองตัว ตัวคั่นที่ 1 จะแยกคู่ต่างๆ ออกจากกัน และตัวคั่นที่ 2 จะแยกแต่ละคู่ |
อื่น ๆ. ฟังก์ชั่น
ฟังก์ชันในตัวหลายฟังก์ชันไม่ได้จัดอยู่ในตระกูลใดๆ ข้างต้น ฟังก์ชันเหล่านี้ครอบคลุมถึงการแฮช ข้อมูลเซสชัน และการเรียกใช้ฟังก์ชันตามอำเภอใจ Java วิธีการ
| ชื่อฟังก์ชั่น | ประเภทผลตอบแทน | Descriptไอออน |
|---|---|---|
| แฮช(a1[, a2…]) | INT | ส่งคืนค่าแฮชของอาร์กิวเมนต์ |
| ผู้ใช้ปัจจุบัน() | เชือก | ส่งคืนชื่อผู้ใช้ปัจจุบันจากตัวจัดการการตรวจสอบสิทธิ์ที่กำหนดค่าไว้ |
| ฐานข้อมูลปัจจุบัน() | เชือก | ส่งคืนชื่อของฐานข้อมูลปัจจุบัน |
| md5 (สตริง/ไบนารี) | เชือก | ส่งคืนค่าตรวจสอบความถูกต้อง MD5 128 บิต ในรูปแบบสตริงตัวเลขฐานสิบหก 32 หลัก หรือค่า NULL สำหรับอาร์กิวเมนต์ที่เป็น NULL |
| sha1 (สตริง/ไบนารี) | เชือก | ส่งคืนค่าแฮช SHA-1 ของอาร์กิวเมนต์ในรูปแบบสตริงเลขฐานสิบหก |
| crc32 (สตริง/ไบนารี) | bigint | ส่งคืนค่าตรวจสอบความซ้ำซ้อนแบบวนรอบ (Cyclic Redundancy Check) ของอาร์กิวเมนต์ที่เป็นสตริงหรือไบนารี |
| รุ่น () | เชือก | ส่งคืนเวอร์ชันของ Hive ในรูปแบบหมายเลขบิลด์ ตามด้วยแฮชของบิลด์ |
| reflect(class, method[, arg1…]) | แตกต่างกันไป | เรียก Java วิธีการโดยการจับคู่ลายเซ็นอาร์กิวเมนต์โดยใช้การสะท้อน (reflection) java_method() เป็นคำพ้องความหมาย |
UDF (ฟังก์ชันที่ผู้ใช้กำหนด)
ใน Hive ผู้ใช้สามารถกำหนดฟังก์ชันของตนเองเพื่อตอบสนองความต้องการของไคลเอ็นต์บางอย่างได้ ฟังก์ชันเหล่านี้เรียกว่า UDF ใน Hive ฟังก์ชันที่ผู้ใช้กำหนดเองเขียนด้วยภาษา Hive Java สำหรับโมดูลเฉพาะ
ฟังก์ชันที่ผู้ใช้กำหนดเอง (UDF) บางตัวได้รับการออกแบบมาโดยเฉพาะเพื่อการนำโค้ดกลับมาใช้ซ้ำในเฟรมเวิร์กของแอปพลิเคชัน นักพัฒนาเป็นผู้เขียนฟังก์ชันเหล่านี้ขึ้นมาเอง Java และผสานรวม UDF เหล่านั้นเข้ากับ Hive
ระหว่างการประมวลผลคำสั่งค้นหา นักพัฒนาสามารถใช้โค้ดได้โดยตรง และ UDF จะส่งคืนผลลัพธ์ตามงานที่ผู้ใช้กำหนด ซึ่งให้ประสิทธิภาพสูงทั้งในด้านการเขียนโค้ดและการประมวลผล
ตัวอย่างเช่น สำหรับการตัดคำในสตริง เราไม่มีฟังก์ชันที่กำหนดไว้ล่วงหน้าใน Hive ดังนั้นเราจึงสามารถเขียนฟังก์ชัน UDF สำหรับการตัดคำได้เอง Java. เมื่อใดก็ตามที่เราต้องการฟังก์ชันการทำงานของ stem เราสามารถเรียกใช้ UDF ของ stem นี้ได้โดยตรงใน Hive
ในที่นี้ ฟังก์ชันการตัดคำหมายถึงการสร้างคำจากรากศัพท์ อัลกอริทึมการตัดคำจะลดคำว่า “wishing”, “wished” และ “wishes” ให้เหลือเพียงรากศัพท์ “wish” ในการทำงานประเภทนี้ เราสามารถเขียน UDF ได้ใน Java และบูรณาการเข้ากับ รัง.
ขึ้นอยู่กับกรณีการใช้งาน ฟังก์ชัน UDF สามารถเขียนให้รับและส่งค่าอินพุตและเอาต์พุตได้จำนวนต่างกัน
โดยทั่วไปแล้ว UDF จะรับค่าอินพุตเพียงค่าเดียวและส่งคืนค่าเอาต์พุตเพียงค่าเดียว หากใช้ UDF ในการสืบค้นข้อมูล UDF นั้นจะถูกเรียกใช้หนึ่งครั้งสำหรับแต่ละแถวในชุดข้อมูลผลลัพธ์
ในทางกลับกัน ฟังก์ชันยังสามารถรับกลุ่มของค่าเป็นอินพุตและส่งคืนค่าเอาต์พุตเดียวได้เช่นกัน ความแตกต่างนี้เองที่เป็นตัวแยกประเภทฟังก์ชันแบบกำหนดเองทั้งสามประเภทที่จะกล่าวถึงต่อไป
UDF ปะทะ UDAF ปะทะ UDTF ใน Hive
ฟังก์ชันแบบกำหนดเองใน Hive จะถูกจัดกลุ่มตามจำนวนแถวที่ป้อนเข้าไปและจำนวนแถวที่ส่งออก การเลือกประเภทที่ไม่ถูกต้องเป็นสาเหตุที่พบบ่อยที่สุดที่ทำให้ฟังก์ชันแบบกำหนดเองไม่สามารถคอมไพล์ได้ หรือส่งคืนเพียงแถวเดียวในขณะที่คาดหวังตาราง
| ประเภท | แถวขาเข้า → แถวขาออก | คลาสเพื่อขยาย | ตัวอย่างในตัว |
|---|---|---|---|
| UDF | หนึ่งแถว → หนึ่งแถว | org.apache.hadoop.hive.ql.exec.UDF | ความยาว(), ปัดเศษ(), กลับด้าน() |
| UDAF | หลายแถว → แถวเดียว | org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver | นับ(), ต่ำสุด(), สูงสุด() |
| UDTF | หนึ่งแถว → หลายแถว | org.apache.hadoop.hive.ql.udf.generic.GenericUDTF | explode(), json_tuple(), parse_url_tuple() |
จากตารางนี้สามารถสรุปเป็นกฎปฏิบัติสองข้อได้ดังนี้:
- โดยทั่วไปแล้ว UDAF มักจะใช้คู่กับคำสั่ง GROUP BY เสมอ เพราะมันจะยุบแต่ละกลุ่มให้เหลือเพียงแถวเดียว
- ไม่สามารถเลือก UDTF ร่วมกับคอลัมน์อื่นๆ ในรายการ SELECT เดียวกันได้ ดังนั้นโดยปกติจึงใช้ร่วมกับ LATERAL VIEW
นอกจากนี้ยังมีคลาสพื้นฐานที่สองซึ่งมีความสามารถมากกว่าสำหรับการทำงานในระดับแถว นั่นคือ GenericUDF ซึ่งรับประเภทข้อมูลที่ซับซ้อน เช่น อาร์เรย์ แผนที่ และโครงสร้าง รวมถึงจำนวนอาร์กิวเมนต์ที่เปลี่ยนแปลงได้
วิธีการเขียนและลงทะเบียน UDF ใน Hive
ตัวอย่างลำต้นที่อธิบายไว้ข้างต้นสามารถสร้างเป็นฟังก์ชันจริงได้ในสี่ขั้นตอน ไม่มีอะไรมากไปกว่านั้น 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 ลงใน classpath ของ 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 ต้องอยู่ในพาธที่คลัสเตอร์ทั้งหมดสามารถอ่านได้ ซึ่งโดยปกติแล้วคือ HDFS
CREATE FUNCTION default.stem AS 'com.guru99.hive.udf.Stem' USING JAR '/user/hive/udfs/hive-udf-1.0.jar';
คลาสเดียวอาจประกาศเมธอด evaluate() ได้มากกว่าหนึ่งเมธอด Hive จะตรวจสอบการเรียกใช้กับรูปแบบของอาร์กิวเมนต์ ซึ่งเป็นเหตุผลว่าทำไมฟังก์ชันหนึ่งจึงสามารถรับได้ทั้งสตริงและจำนวนเต็ม
