Hive - замечательная вещь. Про то, что это и зачем это, написано уже не мало.
В основном все примеры описывают, как делать запросы по хадуповским файлам.
А вот как делать HQL запросы в HBase - информации мало.
Т.к без слёз делать выборки в HBase не получается, пришлось прикручивать Hive
Порядок действий прост.
Создаём в консоли Hive, таблицу связанную с таблицей в HBase, настраиваем мэппинг полей
Исправляем, и... таблица создана.
запускаем тест select * from hive_row_data и видим что всё работает.
Но радоваться рано, простой select запускает обычный перебор, а как только запрос становится чуть сложнее например select * from hive_row_data where key = 'xxx' вот и начинает всё валится (ибо запускается механизм Map - reduce).
В итоге получаем исключение, вот такого плана:
Это значит что map-reduce задачи, запускаемые Hive-ом ничего не знают про HBase, и просто не могут найти нужные jar. Беда в том, что эти библиотеки нужны на всех нодах.
Решение здесь такое:
1. Сохраняем нужные Jar в HDFS (/user/hive/)
В основном все примеры описывают, как делать запросы по хадуповским файлам.
А вот как делать HQL запросы в HBase - информации мало.
Т.к без слёз делать выборки в HBase не получается, пришлось прикручивать Hive
Порядок действий прост.
Создаём в консоли Hive, таблицу связанную с таблицей в HBase, настраиваем мэппинг полей
hive> CREATE EXTERNAL TABLE hive_raw_data(key string, dmp_id string, referrer string, source_id string, source_name string)
> STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
> WITH SERDEPROPERTIES ("hbase.columns.mapping" = "data:dmp_id, data:referrer, data:source_id, data:source_name")
> TBLPROPERTIES("hbase.table.name" = "raw_data");
> STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
> WITH SERDEPROPERTIES ("hbase.columns.mapping" = "data:dmp_id, data:referrer, data:source_id, data:source_name")
> TBLPROPERTIES("hbase.table.name" = "raw_data");
Ууупс, первые грабли. Система не внятно ругается, и никак не создает таблицу. Понять в чем дело - трудно. Оказывается при описании мэппинга ("hbase.columns.mapping" = "data:dmp_id, data:referrer, data:source_id, data:source_name"), не должно быть пробелов между полями! Должно быть вот так: "hbase.columns.mapping" = "data:dmp_id,data:referrer,data:source_id,data:source_name"
Исправляем, и... таблица создана.
запускаем тест select * from hive_row_data и видим что всё работает.
Но радоваться рано, простой select запускает обычный перебор, а как только запрос становится чуть сложнее например select * from hive_row_data where key = 'xxx' вот и начинает всё валится (ибо запускается механизм Map - reduce).
В итоге получаем исключение, вот такого плана:
Exception in thread "Thread-48" java.lang.NullPointerException
at org.apache.hadoop.hive.shims.Hadoop23Shims.getTaskAttemptLogUrl(Hadoop23Shims.java:44)
at org.apache.hadoop.hive.ql.exec.JobDebugger$TaskInfoGrabber.getTaskInfos
(JobDebugger.java:186)
at org.apache.hadoop.hive.ql.exec.JobDebugger$TaskInfoGrabber.run(JobDebugger.java:142)
at java.lang.Thread.run(Thread.java:662)
На самом деле, те исключения которые валятся в консоль, можно игнорировать. Смотреть надо лог джоба. Залазим - смотрим:at org.apache.hadoop.hive.shims.Hadoop23Shims.getTaskAttemptLogUrl(Hadoop23Shims.java:44)
at org.apache.hadoop.hive.ql.exec.JobDebugger$TaskInfoGrabber.getTaskInfos
(JobDebugger.java:186)
at org.apache.hadoop.hive.ql.exec.JobDebugger$TaskInfoGrabber.run(JobDebugger.java:142)
at java.lang.Thread.run(Thread.java:662)
INFO org.apache.hadoop.mapred.TaskInProgress: Error from attempt_201302201311_0003_m_000000_3: java.io.IOException: Cannot create an instance of InputSplit class = org.apache.hadoop.hive.hbase.HBaseSplit:Class
org.apache.hadoop.hive.hbase.HBaseSplit not found at
org.apache.hadoop.hive.ql.io.HiveInputFormat$HiveInputSplit.readFields(HiveInputFormat.java:146)
at org.apache.hadoop.io.serializer.WritableSerialization$WritableDeserializer.deserialize(WritableSerialization.java:73)
at org.apache.hadoop.io.serializer.WritableSerialization$WritableDeserializer.deserialize(WritableSerialization.java:44)
at org.apache.hadoop.mapred.MapTask.getSplitDetails(MapTask.java:351)
at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:367)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:327)
at org.apache.hadoop.mapred.Child$4.run(Child.java:268)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:396)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1332)
at org.apache.hadoop.mapred.Child.main(Child.java:2
at org.apache.hadoop.io.serializer.WritableSerialization$WritableDeserializer.deserialize(WritableSerialization.java:73)
at org.apache.hadoop.io.serializer.WritableSerialization$WritableDeserializer.deserialize(WritableSerialization.java:44)
at org.apache.hadoop.mapred.MapTask.getSplitDetails(MapTask.java:351)
at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:367)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:327)
at org.apache.hadoop.mapred.Child$4.run(Child.java:268)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:396)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1332)
at org.apache.hadoop.mapred.Child.main(Child.java:2
Решение здесь такое:
1. Сохраняем нужные Jar в HDFS (/user/hive/)
hadoop dfs -put /usr/lib/hive/lib/hbase-VERSION.jar /user/hive/hbase-VERSION.jar
hadoop dfs -put /usr/lib/hive/lib/hive-hbase-handler-VERSION.jar /user/hive/hive-hbase-handler-VERSION.jar
в моем случае это выглядит так:hadoop dfs -put /usr/lib/hive/lib/hive-hbase-handler-VERSION.jar /user/hive/hive-hbase-handler-VERSION.jar
hadoop dfs -put /usr/lib/hive/lib/hive-hbase-handler-0.9.0-cdh4.1.3.jar /user/hive/hive-hbase-handler-0.9.0-cdh4.1.3.jar
hadoop dfs -put /usr/lib/hive/lib/hbase-0.92.1-cdh4.1.3-security.jar /user/hive/hbase-0.92.1-cdh4.1.3-security.jar
Затем правим hive-site.xml:hadoop dfs -put /usr/lib/hive/lib/hbase-0.92.1-cdh4.1.3-security.jar /user/hive/hbase-0.92.1-cdh4.1.3-security.jar
<property>
<name>hive.aux.jars.path</name>
<value>/user/hive/hive-hbase-handler-0.9.0-cdh4.1.3.jar,/user/hive/hbase-0.92.1-cdh4.1.3-security.jarN.jar</value>
</property>
Вот и всё. После этого Hive начинает исправно выполнять сложные выборки.<name>hive.aux.jars.path</name>
<value>/user/hive/hive-hbase-handler-0.9.0-cdh4.1.3.jar,/user/hive/hbase-0.92.1-cdh4.1.3-security.jarN.jar</value>
</property>
Работаем и наслаждаемся.
https://cwiki.apache.org/Hive/hbasebulkload.html
Добрый день.
ОтветитьУдалитьА hive-site.xml правили на каждой ноде?
Или как то глобально установили для всех нод?
Добрый день.
ОтветитьУдалитьЯ использовал Клаудеровский пакет. Он позволяет централизованно управлять настройками кластера.
В случае "классического" Хадупа, надо подумать... Возможно и не придется везде править hive-site.xml. Попробуйте его изменить, для начала на той ноде, откуда будете запускать hive - консоль.
О, спасибо за ответ.
ОтветитьУдалитьУ меня тоже cloudera. :)
Общая проблема в том, что к нам приходит файл, для парсинга которого используется внешний Serde, который и подключается в hive-site.xml.
Если на каждной ноде прописать локальный путь к jar-файлу, то hive-консоль отлично работает.
Но при попытке достучаться к таблице через jdbc (утилитка beeline, собственный java класс) или через ODBC, то подключаемый serde-класс не виден. :(
Я исправлял hive-site.xml и через "Cloudera Manager" и у HiveServer2, и у Hive Metastore Server, не цепляется класс.
Есть еще другие способы? :)
Похоже у кого то в classpath, не хватает вашего serde :)
УдалитьНе пробовали предварительно скопировать jar на мастер, в Hive и через консоль сделать "ADD JAR /path/your_serde.jar" с абсолютным путем ?
ADD JAR работает и путем на одной ноде file:///bla1
ОтветитьУдалитьи HDFS hdfs:///bla2
Только все работает в пределах сессии. Стоит выйти из локального hive и заново зайти, то уже не работает. А хочется, чтобы работало всегда.
Как разберетесь, обязательно напишите.
УдалитьПолезный опыт :)