Ví dụ về các hàm trong Hive: Hàm tích hợp sẵn và hàm do người dùng định nghĩa (UDF).

⚡ Tóm tắt thông minh

Các hàm của Hive được chia thành hai nhóm: các hàm tích hợp sẵn đi kèm với công cụ và bao gồm các tác vụ thu thập, ngày tháng, toán học, điều kiện, chuỗi và các tác vụ khác, và các hàm do người dùng định nghĩa được viết bằng ngôn ngữ khác. Java Đối với logic mà Hive không cung cấp.

  • 📚 Sáu nhóm sản phẩm tích hợp sẵn: Các hàm xử lý tập hợp, ngày tháng, toán học, điều kiện, chuỗi và các hàm khác có thể được gọi trực tiếp bên trong HiveQL.
  • 🧾 Chữ ký rất quan trọng: Mỗi hàm đều có danh sách tham số cố định và kiểu trả về được ghi rõ, vì vậy kiểu trả về sẽ quyết định hàm đó có thể được sử dụng ở đâu.
  • 🧩 UDF lấp đầy những khoảng trống: Khi không có hàm tích hợp sẵn, Java Lớp kế thừa từ org.apache.hadoop.hive.ql.exec.UDF cung cấp thao tác còn thiếu.
  • 🔢 Ba dạng chức năng tùy chỉnh: UDF trả về một hàng cho mỗi hàng, UDAF thu gọn nhiều hàng thành một hàng, và UDTF mở rộng một hàng thành nhiều hàng.
  • 🛠️ Đăng ký theo hai bước: Lệnh ADD JAR đưa mã vào classpath và lệnh CREATE TEMPORARY FUNCTION gán tên cho lớp.
  • ♻️ Điểm mấu chốt là tái sử dụng: Một hàm do người dùng định nghĩa (UDF) đã được kiểm thử, chẳng hạn như hàm rút gọn từ gốc từ (stemmer), có thể được gọi từ mọi truy vấn thay vì phải viết lại mỗi lần.

Các hàm trong Hive: Hàm tích hợp sẵn và hàm do người dùng định nghĩa

Các hàm được xây dựng cho một mục đích cụ thể để thực hiện các phép toán như phép toán học, số học, logic và quan hệ trên các toán hạng của tên cột trong bảng.

Chức năng tích hợp sẵn

Đây là những chức năng đã có sẵn trong Hive. Đầu tiên, chúng ta phải kiểm tra yêu cầu của ứng dụng và sau đó chúng ta có thể sử dụng các hàm tích hợp này trong ứng dụng của mình. Chúng ta có thể gọi các hàm này trực tiếp trong ứng dụng của mình.

Cú pháp và các kiểu được đề cập ở phần sau.

Các loại hàm tích hợp sẵn trong Hive:

  • Chức năng thu thập
  • Chức năng ngày
  • Các hàm toán học
  • Hàm có điều kiện
  • Hàm chuỗi
  • Linh tinh. Chức năng

Mỗi trong sáu nhóm hàm được trình bày chi tiết bên dưới cùng với chữ ký hàm và kiểu trả về của chúng.

Chức năng thu thập

Các hàm này được sử dụng cho các tập hợp. Tập hợp có nghĩa là nhómping Chúng là các phần tử, và trả về một phần tử đơn lẻ hoặc một mảng các phần tử tùy thuộc vào kiểu trả về được đề cập trong tên hàm.

Loại trả lại Tên chức năng Mô tả Chi tiết
INT kích thước(Bản đồ ) Nó sẽ truy xuất và cung cấp số lượng thành phần trong loại bản đồ.
INT kích thước (Mảng ) Nó sẽ truy xuất và trả về số lượng phần tử trong kiểu mảng.
Mảng map_keys(Map ) Nó sẽ lấy và trả về một mảng chứa các khóa của bản đồ đầu vào. Mảng này không có thứ tự.
Mảng map_values(Map ) Nó sẽ lấy và trả về một mảng chứa các giá trị của bản đồ đầu vào. Mảng này không có thứ tự.
Mảng sắp xếp_mảng(Mảng) ) Sắp xếp mảng đầu vào theo thứ tự tăng dần của các phần tử và trả về mảng đó.
Boolean mảng chứa (Mảng , giá trị) Trả về TRUE nếu mảng chứa giá trị được truyền làm đối số thứ hai.

Chức năng ngày

Các lệnh này được sử dụng để thực hiện các thao tác xử lý ngày tháng và chuyển đổi kiểu dữ liệu ngày tháng từ kiểu này sang kiểu khác:

Tên chức năng Loại trả lại Mô tả Chi tiết
dấu thời gian unix() BigInt Chúng ta sẽ lấy dòng điện hiện tại Unix Dấu thời gian tính bằng giây. Giá trị này không cố định cho toàn bộ truy vấn.
đến ngày (chuỗi dấu thời gian) ngày Nó sẽ lấy và trả về phần ngày tháng của chuỗi dấu thời gian.
năm(chuỗi ngày) INT Nó sẽ tìm nạp và cung cấp phần năm của ngày hoặc chuỗi dấu thời gian
quý(ngày/dấu thời gian/chuỗi) INT Nó sẽ tìm nạp và đưa ra phần tư trong năm cho ngày, dấu thời gian hoặc chuỗi trong phạm vi từ 1 đến 4
tháng (chuỗi ngày) INT Nó sẽ cung cấp phần tháng của ngày hoặc chuỗi dấu thời gian
giờ(chuỗi ngày) INT Nó sẽ lấy và cung cấp giờ của dấu thời gian.
phút(chuỗi ngày) INT Nó sẽ lấy và cung cấp phút của dấu thời gian.
date_sub(string ngày bắt đầu, int ngày) ngày Nó sẽ truy xuất và trả về kết quả của phép toán con.tractính theo số ngày kể từ ngày bắt đầu.
ngày hiện tại ngày Nó sẽ lấy và cung cấp ngày hiện tại khi bắt đầu quá trình đánh giá truy vấn.
ngày cuối cùng (chuỗi ngày) chuỗi Nó sẽ lấy và trả về ngày cuối cùng của tháng mà ngày đó thuộc về.
trunc(ngày chuỗi, định dạng chuỗi) chuỗi Nó sẽ lấy và trả về ngày tháng được làm tròn đến đơn vị được chỉ định bởi định dạng. Các định dạng được hỗ trợ: THÁNG/THÁNG/MM, NĂM/YYYY/YY.

Các hàm toán học

Các hàm này được sử dụng cho các phép toán học. Thay vì tạo các hàm do người dùng định nghĩa (UDF), chúng ta có một số hàm toán học tích hợp sẵn trong Hive.

Tên chức năng Loại trả lại Mô tả Chi tiết
tròn (ĐÔI X) GẤP ĐÔI Nó sẽ lấy và trả về giá trị BIGINT được làm tròn của X.
vòng(DOUBLE X, INT d) GẤP ĐÔI Nó sẽ lấy và trả về X được làm tròn đến d chữ số thập phân.
tròn (DOUBLE X) GẤP ĐÔI Nó sẽ lấy và trả về giá trị BIGINT đã được làm tròn của X bằng chế độ làm tròn HALF_EVEN, còn được gọi là làm tròn kiểu ngân hàng.
sàn nhà (DOUBLE X) LỚN Nó sẽ lấy và trả về giá trị BIGINT lớn nhất bằng hoặc nhỏ hơn giá trị X.
trần nhà(ĐÔI a), trần nhà(ĐÔI a) LỚN Nó sẽ lấy và trả về giá trị BIGINT nhỏ nhất bằng hoặc lớn hơn giá trị a.
rand(), rand(hạt giống INT) GẤP ĐÔI Chương trình sẽ lấy và trả về một số ngẫu nhiên được phân bố đều từ 0 đến 1. Việc cung cấp một giá trị "hạt giống" (seed) sẽ giúp chuỗi số lặp lại.

Hàm có điều kiện

Các hàm này được sử dụng để kiểm tra giá trị có điều kiện.

Tên chức năng Loại trả lại Mô tả Chi tiết
if(Điều kiện kiểm tra Boolean, T valueTrue, T valueFalseOrNull) T Nó sẽ trả về valueTrue khi testCondition đúng, và valueFalseOrNull trong trường hợp ngược lại.
isnull(X) Boolean Nó sẽ truy xuất và trả về true nếu X là NULL và false nếu ngược lại.
không rỗng (X) Boolean Nó sẽ truy xuất và trả về true nếu X không phải là NULL và false nếu ngược lại.
nvl(T value, T default_value) T Nó sẽ trả về default_value khi value là NULL, và trả về value trong các trường hợp khác.

Hàm chuỗi

Các thao tác và phép toán trên chuỗi được xử lý bởi các hàm sau.

Tên chức năng Loại trả lại Mô tả Chi tiết
đảo ngược (chuỗi X) chuỗi Nó sẽ cho chuỗi đảo ngược của X
rpad(chuỗi str, độ dài int, pad chuỗi) chuỗi Nó sẽ lấy và trả về chuỗi str được đệm bằng ký tự đệm ở bên phải cho đến tổng chiều dài là length.
rtrim(string X) chuỗi Nó sẽ lấy và trả về chuỗi kết quả sau khi loại bỏ khoảng trắng ở cuối (phía bên phải) của X.
Ví dụ, rtrim(' results ') trả về ' kết quả'
dấu cách(INT n) chuỗi Nó sẽ lấy và trả về một chuỗi gồm n khoảng trắng.
chia(STRING str, STRING vỗ) mảng Tách str xung quanh pat (pat là một biểu thức chính quy).
str_to_map(text[, delimiter1, delimiter2]) bản đồ Nó sẽ chia văn bản thành các cặp khóa-giá trị bằng cách sử dụng hai dấu phân cách. Dấu phân cách 1 dùng để tách các cặp và dấu phân cách 2 dùng để tách từng cặp.

Linh tinh. Chức năng

Một số hàm tích hợp sẵn không thuộc bất kỳ nhóm nào nêu trên. Chúng bao gồm các hàm băm, thông tin phiên và gọi các hàm tùy ý. Java phương pháp.

Tên chức năng Loại trả lại Mô tả Chi tiết
băm(a1[, a2…]) INT Trả về giá trị băm của các đối số.
người dùng hiện tại() chuỗi Trả về tên người dùng hiện tại từ trình quản lý xác thực đã được cấu hình.
cơ sở dữ liệu hiện tại() chuỗi Trả về tên của cơ sở dữ liệu hiện tại.
md5 (chuỗi/nhị phân) chuỗi Trả về mã kiểm tra MD5 128 bit dưới dạng chuỗi 32 chữ số thập lục phân, hoặc NULL nếu đối số là NULL.
sha1 (chuỗi/nhị phân) chuỗi Trả về mã băm SHA-1 của đối số dưới dạng chuỗi thập lục phân.
crc32 (chuỗi/nhị phân) BigInt Trả về giá trị kiểm tra dư tuần hoàn của một chuỗi hoặc đối số nhị phân.
phiên bản() chuỗi Trả về phiên bản Hive dưới dạng số bản dựng theo sau là mã băm bản dựng.
phản chiếu(lớp, phương thức[, đối số 1…]) thay đổi Gọi một Java phương thức bằng cách khớp chữ ký đối số, sử dụng phản chiếu. java_method() là từ đồng nghĩa.

UDF (Hàm do người dùng xác định)

Trong Hive, người dùng có thể định nghĩa các hàm riêng của họ để đáp ứng các yêu cầu cụ thể của khách hàng. Chúng được gọi là UDF trong Hive. Các hàm do người dùng định nghĩa được viết bằng ngôn ngữ lập trình Hive. Java cho các mô-đun cụ thể.

Một số hàm do người dùng định nghĩa (UDF) được thiết kế đặc biệt để tái sử dụng mã trong các khung ứng dụng. Nhà phát triển viết các hàm này trong... Java và tích hợp các UDF đó với Hive.

Trong quá trình thực thi truy vấn, nhà phát triển có thể trực tiếp sử dụng mã, và các hàm do người dùng định nghĩa (UDF) sẽ trả về kết quả theo các tác vụ do người dùng xác định. Điều này mang lại hiệu suất cao về mặt lập trình và thực thi.

Ví dụ, đối với việc rút gọn chuỗi, chúng ta không có hàm được định nghĩa sẵn trong Hive. Vì vậy, chúng ta có thể viết một hàm UDF rút gọn chuỗi trong Hive. JavaBất cứ khi nào cần chức năng xử lý thân cây, chúng ta có thể gọi trực tiếp hàm UDF xử lý thân cây này trong Hive.

Ở đây, chức năng xử lý gốc từ có nghĩa là tạo ra các từ từ các từ gốc của chúng. Thuật toán xử lý gốc từ sẽ rút gọn các từ “wishing”, “wished” và “wishes” về từ gốc “wish”. Để thực hiện loại chức năng này, chúng ta có thể viết một hàm do người dùng định nghĩa (UDF) trong Java và tích hợp nó với Tổ ong.

Tùy thuộc vào trường hợp sử dụng, hàm do người dùng định nghĩa (UDF) có thể được viết để chấp nhận và tạo ra số lượng giá trị đầu vào và đầu ra khác nhau.

Kiểu hàm UDF thông thường sẽ chấp nhận một giá trị đầu vào duy nhất và tạo ra một giá trị đầu ra duy nhất. Nếu hàm UDF được sử dụng trong một truy vấn, thì hàm UDF sẽ được gọi một lần cho mỗi hàng trong tập dữ liệu kết quả.

Ngược lại, một hàm có thể chấp nhận một nhóm giá trị làm đầu vào và trả về một giá trị đầu ra duy nhất. Sự khác biệt đó là điều phân biệt ba loại hàm tùy chỉnh được mô tả tiếp theo.

UDF so với UDAF so với UDTF trong Hive

Các hàm tùy chỉnh trong Hive được nhóm theo số lượng hàng đầu vào và số lượng hàng đầu ra. Việc chọn sai kiểu dữ liệu là lý do phổ biến nhất khiến một hàm tùy chỉnh không biên dịch được hoặc trả về một hàng duy nhất trong khi mong đợi một bảng.

Kiểu Hàng vào → hàng ra Lớp học mở rộng Ví dụ tích hợp sẵn
UDF Một hàng → một hàng org.apache.hadoop.hive.ql.exec.UDF độ dài(), làm tròn(), đảo ngược()
UDAF Nhiều hàng → một hàng org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver đếm(), giá trị nhỏ nhất(), giá trị lớn nhất()
UDTF Một hàng → nhiều hàng org.apache.hadoop.hive.ql.udf.generic.GenericUDTF explode(), json_tuple(), parse_url_tuple()

Từ bảng trên, ta có thể rút ra hai quy tắc thực tiễn sau:

  • UDAF hầu như luôn được ghép nối với mệnh đề GROUP BY, bởi vì nó thu gọn mỗi nhóm thành một hàng duy nhất.
  • Không thể chọn một UDTF cùng với các cột khác trong cùng một danh sách SELECT, vì vậy nó thường được sử dụng với LATERAL VIEW.

Ngoài ra còn có một lớp cơ sở thứ hai, mạnh mẽ hơn, dành cho công việc ở cấp hàng, GenericUDF, chấp nhận các kiểu dữ liệu phức tạp như mảng, bản đồ và cấu trúc, cùng với số lượng tham số thay đổi.

Cách viết và đăng ký hàm do người dùng định nghĩa (UDF) trong Hive

Ví dụ về thân cây được mô tả ở trên có thể được xây dựng thành một hàm thực sự trong bốn bước. Không có gì vượt quá một... Java Cần có trình biên dịch và một phiên Hive đang hoạt động.

Bước 1) Viết thư cho Java Lớp này kế thừa từ UDF và triển khai phương thức `evaluate()` công khai. Hive gọi phương thức `evaluate()` một lần cho mỗi hàng, vì vậy phương thức này phải xử lý được đầu vào 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);
    }
}

Bước 2) Biên dịch lớp và đóng gói nó vào một tệp JAR, ví dụ: hive-udf-1.0.jar, cùng với bất kỳ lớp nào mà nó phụ thuộc.

Bước 3) Đặt tệp JAR vào classpath của Hive và gán tên hàm cho lớp đó. Hàm tạm thời chỉ tồn tại trong phiên hiện tại.

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

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

Bước 4) Gọi hàm mới giống hệt như một hàm có sẵn. Khi áp dụng cho các từ “wishing”, “wished” và “wishes”, lớp này sẽ trả về “wish” cho cả ba từ.

SELECT word, stem(word) FROM words;

Để đảm bảo chức năng này khả dụng cho mọi phiên và mọi người dùng, hãy đăng ký nó vĩnh viễn vào cơ sở dữ liệu. Tệp JAR phải nằm trên một đường dẫn mà toàn bộ cụm máy chủ có thể đọc được, thông thường là HDFS.

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

Một lớp duy nhất có thể khai báo nhiều hơn một phương thức evaluate(). Hive so khớp lệnh gọi với chữ ký đối số, đó là lý do tại sao một hàm có thể chấp nhận cả chuỗi và số nguyên.

Câu Hỏi Thường Gặp

Lệnh SHOW FUNCTIONS liệt kê mọi tên hàm đã đăng ký, bao gồm cả các tên hàm tùy chỉnh. Lệnh DESCRIBE FUNCTION name in ra chữ ký hàm trên một dòng, và lệnh DESCRIBE FUNCTION EXTENDED name bổ sung các ví dụ sử dụng nếu lớp triển khai cung cấp chúng.

Hầu hết các trường hợp đều là vấn đề về tên hoặc phạm vi: chuỗi sau AS phải là tên lớp đủ điều kiện, và ADD JAR chỉ áp dụng cho phiên đã chạy lệnh đó. Kết nối lại sẽ xóa cả JAR và bất kỳ hàm tạm thời nào.

Hãy sử dụng GenericUDF khi hàm nhận các kiểu dữ liệu phức tạp như mảng, map hoặc struct, số lượng tham số thay đổi, hoặc cần tự kiểm tra kiểu dữ liệu của tham số. Lớp UDF đơn giản sẽ phân giải kiểu dữ liệu bằng phản chiếu và chỉ xử lý các kiểu dữ liệu Writable nguyên thủy.

Một hàm UDF thực sự phải chạy trên JVM. Đối với các ngôn ngữ khác, Tổ ong cung cấp mệnh đề TRANSFORM, cho phép truyền từng hàng thông qua một tập lệnh bên ngoài, chẳng hạn như... Python Thông qua đầu vào và đầu ra tiêu chuẩn. Phương pháp này chậm hơn nhưng tránh được... Java hoàn toàn.

Điều đó hoàn toàn có thể xảy ra. Phương thức `evaluate()` chạy một lần cho mỗi hàng, do đó logic tốn kém sẽ được nhân lên theo số lượng hàng, và việc cấp phát đối tượng bên trong phương thức sẽ làm tăng áp lực thu gom rác. Nên ưu tiên sử dụng hàm tích hợp sẵn nếu có, và giữ cho phương thức `evaluate()` không cần thực hiện các thao tác I/O.

Không. Tên hàm không phân biệt chữ hoa chữ thường, vì vậy ROUND(), Round() và round() đều là cùng một hàm. Java Tên lớp trong mệnh đề AS là một vấn đề khác và phải khớp chính xác với lớp đã biên dịch, bao gồm cả gói của nó.

Các trợ lý học máy sẽ ánh xạ mô tả bằng ngôn ngữ thông thường sang các chữ ký ứng cử viên và cảnh báo khi kiểu dữ liệu trả về không phù hợp với cột mục tiêu. Hãy xác minh đề xuất so với chữ ký đã được ghi lại, vì các tên được tạo ra đôi khi thuộc về một phương ngữ SQL khác.

Nó tạo ra một khung sườn có thể sử dụng được — phần khai báo lớp, các phần nhập khẩu và phương thức evaluate() — từ một chú thích mô tả hoạt động. Việc xử lý giá trị null, các kiểu dữ liệu có thể ghi và bước đóng gói vẫn cần được xem xét lại, và hàm này phải được kiểm thử trên các hàng dữ liệu thực tế.

Tóm tắt bài viết này với: