Big Data от A до Я. Часть 5.2: Продвинутые возможности hive

Привет, Хабр! В этой статье мы продолжим рассматривать возможности hive — движка, транслирующего SQL-like запросы в MapReduce задачи.

В предыдущей статье мы рассмотрели базовые возможности hive, такие как создание таблиц, загрузка данных, выполнение простых SELECT-запросов. Теперь поговорим о продвинутых возможностях, которые позволят выжимать максимум из Hive.

eeb0cefcff6cfe83badacfa667e1127d.png

User Defined Functions


Одним из основных препятствий при работе с Hive является скованность рамками стандартного SQL. Эту проблему можно решить при помощи использования расширений языка — так называемых «User Defined Functions». Довольно много полезных функций встоено прямо в язык Hive. Приведу несколько самых интересных на мой взгляд (информация взята из оффициальной документации):

Json

Довольно частой задачей при работе с большими данынми является обработка неструктурированных данных, хранящихся в формате json. Для работы с json hive поддерживать специальный метод get_json_object, позволяющий извлекать значения из json-документов. Для извлечения значений из объекта используется ограниченная версия нотации JSONPath. Поддерживаются следующие операции:

  • $: Возвращает корневой объект
  • .: Вовзращает объект-ребенок
  • []: Обращение по индексу в массиве
  • *: Wildcard для

Примеры работы с Json из оффициальной документаци:

Пусть есть таблица: src_json, состоящаяя из одной колонки (jsoin) и одной строки:

{"store":
  {"fruit":\[{"weight":8,"type":"apple"},{"weight":9,"type":"pear"}],
   "bicycle":{"price":19.95,"color":"red"}
  },
 "email":"amy@only_for_json_udf_test.net",
 "owner":"amy"
}

Примеры запросов к таблице:
hive> SELECT get_json_object(src_json.json, '$.owner') FROM src_json;
amy
 
hive> SELECT get_json_object(src_json.json, '$.store.fruit\[0]') FROM src_json;
{"weight":8,"type":"apple"}
 
hive> SELECT get_json_object(src_json.json, '$.non_exist_key') FROM src_json;
NULL

Xpath

Аналогично, если данные которые необходимо обрабатывать при помощи hive хранятся не в json, а в XML — их можно обрабатыватывать при помощи функции xpath, позвоялющей парсить XML при помощи соответствующего языка. Пример парсинга xml-данных при помощи xpath:

hive> select xpath('b1b2','a/*/text()') from sample_table limit 1 ;
["b1","b2"]

Другие полезные встроенные функции:

Встроенная библиотека содержит довольно богатый набор встроенных функций. Можно выделить несколько групп:

  • Математические функции (sin, cos, log, …)
  • Функции работы со временем (from_unix_timestamp, to_date, current date, hour (string date), timediff, …) — очень богатый выбор функций для преобразования дат и времени
  • Функции для работы со строками. Поддерживаются как общеприменимые функции, такие как lengh, reverse, regexp, так и специфичные — типа parse_url или уже рассмотренной get_json_object)
  • Много различных системных функций — current_user, current_database, …
  • Криптографические функции — sha, md5, aes_encrypt, aes_decrypt…

Полный список встроенных в hive функций можно найти по ссылке.

Написание собственных UDF


Не всегда бывает достаточно встроенных в hive функций для решения поставленной задачи. Если встроенной функции не нашлось — можно написать свою UDF. Делается это на языке java.

Разберем создание собственной UDF на примере простой функции преобразования строки в lowercase:

1. Создадим пакет com/example/hive/udf и создадим в нем класс Lower.java:

mkdir -p com/example/hive/udf
edit  com/example/hive/udf/Lower.java

2. Реализуем собственно класс Lower:
package com.example.hive.udf;

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

public final class Lower extends UDF {
  public Text evaluate(final Text s) {
    if (s == null) { return null; }
    return new Text(s.toString().toLowerCase());
  }
}

3. Добавим необходимые библиотеки в CLASSPATH (в вашем hadoop-дистрибутиве ссылки на jar-файлы могут быть немного другими):
export CLASSPATH=/opt/cloudera/parcels/CDH/lib/hive/lib/hive-exec.jar:/opt/cloudera/parcels/CDH/lib/hadoop/hadoop-common.jar

4. Компилируем нашу UDF-ку и собираем jar-архив:
javac com/example/hive/udf/Lower.java
jar cvf my_udf.jar *

5. Для того чтобы можно было использовать функцию в hive — нужно явно ее декларировать:
hive> ADD JAR my_udf.jar;

hive> create temporary function my_lower as 'com.example.hive.udf.Lower';

hive> select my_lower('HELLO') from sample_table limit 1;
hello

Трансформация таблицы при помощи скриптов


Еще одним способом расширения стандартного функционала HIVE является использование метода TRANSFORM, который позволяет преобразовывать данные при помощи кастомных скриптов на любом языке программирования (особенно это подходит тем кто не любит java и не хочет писать на ней udf-ки).  

Синтаксис для использования команды следующий:

SELECT TRANSFORM() USING