Dieser Blogbeitrag wurde vor der Fusion mit Cloudera auf Hortonworks.com veröffentlicht. Einige Links, Ressourcen oder Referenzen sind möglicherweise nicht mehr korrekt.
Dies ist der erste von zwei Beiträgen, in denen die Verwendung von Hive für die Interaktion mit HBase-Tabellen untersucht wird. Der zweite Beitrag ist hier.
Eines der Dinge, zu denen ich häufig gefragt werde, ist die Verwendung von HBase von Apache Hive. Nicht nur, wie es geht, sondern was funktioniert, wie gut es funktioniert und wie man es sinnvoll nutzt. Ich habe in diesem Bereich ein wenig recherchiert, also wird dies hoffentlich für jemanden außer mir nützlich sein. Dies ist ein Thema, das wir in HBase in Aktion nicht behandeln konnten. Vielleicht werden diese Hinweise die Grundlage für die 2. Ausgabe 😉 Diese Hinweise gelten für Hive 0.11.x, das in Verbindung mit HBase 0.94.x verwendet wird. Sie sollten weitgehend auf 0.12.x + 0.96.x anwendbar sein, obwohl ich noch nicht alles getestet habe.
Das Hive-Projekt enthält eine optionale Bibliothek für die Interaktion mit HBase. Hier wird die Brückenschicht zwischen den beiden Systemen implementiert. Die primäre Schnittstelle, die Sie verwenden, wenn Sie über Hive-Abfragen auf HBase zugreifen, heißt BaseStorageHandler
. Sie können auch direkt über Eingabe- und Ausgabeformate mit HBase-Tabellen interagieren, aber der Handler ist einfacher und funktioniert für die meisten Zwecke.
HBase-Tabellen von Hive
Verwenden Sie den HBaseStorageHandler
um HBase-Tabellen beim Hive-Metastore zu registrieren. Optional können Sie die HBase-Tabelle als EXTERNAL
angeben , in diesem Fall erstellt Hive nicht, um diese Tabelle direkt zu löschen – Sie müssen dazu die HBase-Shell verwenden.
[sql]
CREATE [EXTERNAL] TABLE foo(…)
GESPEICHERT VON 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
TBLPROPERTIES ('hbase.table.name' =' bar');
[/sql]
Die obige Anweisung registriert die HBase-Tabelle namens bar
im Hive-Metastore, auf den von Hive aus unter dem Namen foo
zugegriffen werden kann .
Unter der Haube, HBaseStorageHandler
delegiert die Interaktion mit der HBase-Tabelle anHiveHBaseTableInputFormat
und HiveHBaseTableOutputFormat
. Wenn Sie möchten, können Sie Ihre HBase-Tabelle mithilfe dieser Klassen direkt in Hive registrieren. Die obige Aussage entspricht ungefähr:
[sql]
CREATE TABLE foo(…)
STORED AS
INPUTFORMAT 'org.apache.hadoop.hive.hbase.HiveHBaseTableInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive .hbase.HiveHBaseTableOutputFormat'
TBLPROPERTIES ('hbase.table.name' ='bar');
[/sql]
Ebenfalls bereitgestellt wird das HiveHFileOutputFormat
was bedeutet, dass es auch möglich sein sollte, HFiles für das Bulkloading von Hive zu generieren. In der Praxis habe ich es nicht durchgängig zum Laufen gebracht (siehe HIVE-4627).
Schemazuordnung
Die Registrierung des Tisches ist nur der erste Schritt. Im Rahmen dieser Registrierung müssen Sie auch eine Spaltenzuordnung angeben. So verknüpfen Sie Hive-Spaltennamen mit dem Zeilenschlüssel und den Spalten der HBase-Tabelle. Verwenden Sie dazu hbase.columns.mapping
SerDe-Eigenschaft.
[sql]
CREATE TABLE foo(rowkey STRING, a STRING, b STRING)
GESPEICHERT VON 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
MIT SERDEPROPERTIES ('hbase.columns .mapping' =':key,f:c1,f:c2')
TBLPROPERTIES ('hbase.table.name' ='bar');
…
[/sql]
Die in der Zuordnungseigenschaft bereitgestellten Werte entsprechen eins zu eins den Spaltennamen der Hive-Tabelle. HBase-Spaltennamen sind vollständig nach Spaltenfamilie qualifiziert und Sie verwenden das spezielle Token :key
um den Zeilenschlüssel darzustellen. Oben
Beispiel erstellt Zeilen aus der HBase-Tabelle bar
verfügbar über die Hive-Tabelle foo
. Der foo
Spalte rowkey
wird dem Zeilenschlüssel der HBase-Tabelle zugeordnet, a
zu c1
im f
Spaltenfamilie und b
zu c2
, auch im f
Familie.
Sie können auch Hives MAP
zuordnen Datenstrukturen zu HBase-Spaltenfamilien. In diesem Fall nur der STRING
Hive-Typ wird verwendet. Der andere derzeit unterstützte Hive-Typ ist BINARY
. Weitere Beispiele finden Sie auf der Wiki-Seite.
Interaktion mit Daten
Wenn die Spaltenzuordnungen definiert sind, können Sie jetzt wie auf andere Hive-Daten auf HBase-Daten zugreifen. Derzeit werden nur einfache Abfrageprädikate unterstützt.
[sql]
SELECT * FROM foo WHERE …;
[/sql]
Sie können auch eine HBase-Tabelle mit Hive füllen. Dies funktioniert sowohl mit INTO
und OVERWRITE
Klauseln.
[sql]
FROM source_hive_table INSERT INTO TABLE my_hbase_table
SELECT source_hive_table.* WHERE …;
[/sql]
Beachten Sie, dass es in Hive 0.12.0 eine Regression gibt, die diese Funktion unterbricht, siehe HIVE-5515.
In der Praxis
Es ist immer noch ein wenig Fingerspitzengefühl erforderlich, um zur Laufzeit alles richtig zu verkabeln. Das HBase-Interaktionsmodul ist vollständig optional, daher müssen Sie sicherstellen, dass es und seine HBase-Abhängigkeiten im Klassenpfad von Hive verfügbar sind.
[bash]
$ export HADOOP_CLASSPATH=…
$ hive -e „CREATE TABLE … STORED BY ‚org.apache…HBaseStorageHandler‘“
[/bash]
Die Installationsumgebung könnte dies für Nutzer besser handhaben, aber im Moment müssen Sie es selbst verwalten. Idealerweise der hive
bin-Skript kann das Vorhandensein von HBase erkennen und automatisch den erforderlichen CLASSPATH
erstellen Anpassungen. Diese Verbesserung scheint in HIVE-2055 verfolgt zu werden. Die letzte Meile wird von der Distribution selbst bereitgestellt, um sicherzustellen, dass die Umgebungsvariablen auf hive
gesetzt sind . Diese Funktion wird von BIGTOP-955 bereitgestellt.
Sie müssen auch sicherstellen, dass die erforderlichen JAR-Dateien an die MapReduce-Jobs gesendet werden, wenn Sie Ihre Hive-Anweisungen ausführen. Hive bietet einen Mechanismus zum Senden zusätzlicher Jobabhängigkeiten über die Auxjars-Funktion.
[bash]
$ export HIVE_AUX_JARS_PATH=…
$ hive -e „SELECT * FROM …“
[/bash]
Ich habe einen kleinen Fehler in HDP-1.3-Builds entdeckt, der benutzerdefinierte Werte von HIVE_AUX_JARS_PATH
maskiert . Mit Administratorrechten lässt sich dies leicht beheben, indem die Zeile in hive-env.sh
korrigiert wird einen bestehenden Wert zu respektieren. Der
Workaround in Benutzerskripten ist die Verwendung von SET
-Anweisung, um einen Wert anzugeben, nachdem Sie die Hive-Befehlszeile gestartet haben.
[bash]
SET hive.aux.jars.path =…
[/bash]
Hive sollte in der Lage sein, zu erkennen, welche Gläser notwendig sind, und sie selbst hinzuzufügen. HBase stellt die TableMapReduceUtils#addDependencyJars
bereit Methoden dazu. Es scheint, dass dies in hive-0.12.0 erfolgt, zumindest laut HIVE-2379.
Zukunftsarbeit
Es wurde viel über die richtige Unterstützung für Prädikat-Pushdown (HIVE-1643, HIVE-2854, HIVE-3617,
HIVE-3684) und Datentyperkennung (HIVE-1245, HIVE-2599) gesprochen. Diese gehen Hand in Hand, da die Prädikatensemantik in Bezug auf die Typen definiert ist, auf denen sie operiert. Es könnte mehr getan werden, um die komplexen Datentypen von Hive wie Maps und Structs auch HBase-Spaltenfamilien zuzuordnen (HIVE-3211). Die Unterstützung für HBase-Zeitstempel ist ein bisschen chaotisch. Sie werden Hive-Anwendungen nicht mit beliebiger Granularität zur Verfügung gestellt (HIVE-2828, HIVE-2306). Die einzige Interaktion, die ein Nutzer hat, ist die Speicher-Handler-Einstellung zum Schreiben eines benutzerdefinierten Zeitstempels mit allen Vorgängen.
Aus Leistungssicht gibt es Dinge, die Hive heute tun kann (d. h. unabhängig von Datentypen), um die Vorteile von HBase zu nutzen. Es besteht auch die Möglichkeit eines HBase-fähigen Hive, HBase-Tabellen als Zwischenspeicherort (HIVE-3565) zu verwenden, wodurch kartenseitige Verknüpfungen mit in HBase geladenen Dimensionstabellen erleichtert werden. Hive könnte die natürliche indizierte Struktur von HBase (HIVE-3634, HIVE-3727) nutzen und möglicherweise riesige Scans einsparen. Derzeit hat der Nutzer keine (irgendeine?) Kontrolle über die ausgeführten Scans. Die Konfiguration pro Job oder zumindest pro Tabelle sollte aktiviert werden (HIVE-1233). Das würde es einem HBase-erfahrenen Benutzer ermöglichen, Hive Hinweise zu geben, wie es mit HBase interagieren sollte. Die Unterstützung für einfaches Split-Sampling von HBase-Tabellen (HIVE-3399) könnte ebenfalls problemlos erfolgen, da HBase bereits Tabellenpartitionen verwaltet.
Andere Zugriffskanäle
Alles, was bisher besprochen wurde, erforderte, dass Hive mit Online-HBase-Regionsservern interagierte. Anwendungen können einen erheblichen Durchsatz und eine größere Flexibilität erzielen, indem sie direkt mit HBase-Daten interagieren, die in HDFS gespeichert werden. Dies hat auch den Vorteil, dass Hive-Workloads daran gehindert werden, Online-SLA-gebundene HBase-Anwendungen zu stören (zumindest bis wir HBase-Verbesserungen bei der QOS-Isolierung zwischen Aufgaben sehen, HBASE-4441).
Wie bereits erwähnt, gibt es das HiveHFileOutputFormat
. Das Auflösen von HIVE-4627 sollte Hive zu einer unkomplizierten Möglichkeit zum Generieren von HFiles für das Massenladen machen. Nachdem Sie die HFiles mit Hive erstellt haben, müssen Sie als letzten Schritt noch LoadIncrementalHFiles
ausführen Dienstprogramm, um sie zu kopieren und in den Regionen zu registrieren. Dazu der HiveStorageHandler
Die Benutzeroberfläche benötigt eine Art Hook, um den Abfrageplan bei der Erstellung zu beeinflussen und ihm das Anhängen von Schritten zu ermöglichen. Einmal eingerichtet, sollte es möglich sein, SET
ein Laufzeit-Flag, das einen INSERT
umschaltet Vorgang zur Verwendung von Bulkload.
HBase hat kürzlich die Tabellen-Snapshot-Funktion eingeführt. Dadurch kann ein Nutzer eine persistente Point-in-Time-Ansicht einer Tabelle erstellen, die in HDFS persistent gespeichert wird. HBase kann eine Tabelle aus einem Snapshot in einen früheren Zustand zurückversetzen und aus einem vorhandenen Snapshot eine völlig neue Tabelle erstellen. Hive unterstützt derzeit nicht das Lesen aus einem HBase-Snapshot. HBase unterstützt übrigens noch keine MapReduce-Jobs über Snapshots, obwohl die Funktion noch in Arbeit ist (HBASE-8369).
Schlussfolgerungen
Die Schnittstelle zwischen HBase und Hive ist jung, hat aber gutes Potenzial. Es gibt eine Menge niedrig hängender Früchte, die aufgegriffen werden können, um die Dinge einfacher und schneller zu machen. Das eklatanteste Problem, das eine echte Anwendungsentwicklung verhindert, ist die Impedanzabweichung zwischen dem typisierten, dichten Schema von Hive und dem nicht typisierten, spärlichen Schema von HBase. Dies ist ebenso ein kognitives Problem wie ein technisches Problem. Lösungen hier würden eine Reihe von Verbesserungen ermöglichen, einschließlich vieler Leistungsverbesserungen. Ich hoffe, dass die weitere Arbeit zum Hinzufügen von Datentypen zu HBase (HBASE-8089) dazu beitragen kann, diese Lücke zu schließen.
Grundlegende Operationen funktionieren meistens, zumindest rudimentär. Mit Hive können Sie Daten aus HBase lesen und wieder in HBase schreiben. Die Konfiguration der Umgebung ist ein undurchsichtiger und manueller Prozess, der Neulinge wahrscheinlich davon abhält, die Tools zu übernehmen. Es stellt sich auch die Frage nach Massenvorgängen – die Unterstützung für das Schreiben von HFiles und das Lesen von HBase-Snapshots mit Hive fehlt derzeit vollständig. Und natürlich sind überall Bugs verstreut. Die größte aktuelle Verbesserung ist die Einstellung der Benutzeroberfläche von HCatalog, wodurch die notwendige Vorabentscheidung hinsichtlich der zu verwendenden Benutzeroberfläche entfällt.
Hive bietet zusätzlich zu HBase eine sehr benutzerfreundliche SQL-Schnittstelle, die sich problemlos in viele bestehende ETL-Workflows integrieren lässt. Diese Schnittstelle erfordert die Vereinfachung einiger der von HBase bereitgestellten BigTable-Semantiken, aber das Ergebnis wird sein, dass HBase für ein viel breiteres Publikum von Benutzern geöffnet wird. Die Hive-Interop ergänzt die von Phoenix bereitgestellte Erfahrung sehr gut. Hive hat den Vorteil, dass es nicht die Bereitstellungskomplexität erfordert, die derzeit von diesem System benötigt wird. Hoffentlich ermöglicht die gemeinsame Definition von Typen eine komplementäre Zukunft.