HiveからElasticsearchに接続してみる

仕事ではElasticsearchを使っているのですが、それ以外にGitやS3に大量のJSONがあり、これをElasticsearchを組み合わせた検索ができないものかと思い、先日1.0がリリースされたばかりのApache Drillを試しています。

ただし、Drillは現時点ではElasticsearchをサポートしておらず、Elasticsearch側でもDrillのサポートは提供されていません。そこで、Hive経由でElasticsearchにDrillからアクセスできないものかと考えてみました。

Hiveのインストール

まずはHiveを実行できるようにします。

HadoopとHiveのディストリビューションを取得して適当なディレクトリに展開し、環境変数HADOOP_HOMEにHadoopを展開したディレクトリのパスを指定しておきます。また、Hiveではデフォルトでは/user/hive/warehouseにデータを作成しようとしますが、Hiveを実行するユーザにパーミッションがない場合は~/.hivercに以下のような設定を行っておく必要があるみたいです。

SET hive.metastore.warehouse.dir=${env:HOME}/Documents/hive-warehouse;

Hiveを展開したディレクトリ内のbin/hiveコマンドを実行するとHiveの対話シェルを起動できます。

elasticsearch-hadoopの導入

Elasticsearchはelasticsearch-hadoopとしてHadoopのサポートが提供されており、この中にHiveのサポートも含まれています(elasticsearch-hadoopではSparkなどもサポートされています)。

使い方は簡単で、ここからZIPファイルをダウンロードし、その中に含まれているelasticsearch-hadoopのJARファイルを以下のようにHiveの起動時に--auxpathオプションで指定します。この他にも、elasticsearch-hadoopのドキュメントではADDコマンドで追加したり、hive-site.xmlで設定する方法も紹介されています。

hive --auxpath elasticsearch-hadoop-2.0.jar

テーブルの作成

Hiveの対話シェルで以下のような感じでテーブルを作成します。Elasticsearchで配列になっているプロパティはarray<string>のようにマッピングすればいいみたいです。

CREATE EXTERNAL TABLE blog (
  title string,
  content string,
  published_on timestamp,
  tags array<string>
)
STORED BY 'org.elasticsearch.hadoop.hive.EsStorageHandler'
TBLPROPERTIES(
  'es.resource' = 'blog/article'
);

ElasticsearchとHiveが別のマシンで起動している場合はes.nodesやes.portを指定します。

TBLPROPERTIES(
  'es.resource' = 'blog/article',
  'es.nodes' = 'localhost',
  'es.port' = '9200'
);

検索してみる

準備ができたのでHiveの対話シェルで検索してみます。

hive> select * from blog;
OK
増し増しに沈没	ラーメン二郎にチャレンジしました
増し増しに撃沈
胃薬飲んでかえります	2013-08-31 22:07:18	["ラーメン二郎"]
Time taken: 1.612 seconds, Fetched: 1 row(s)

できました!あとはこのテーブルをDrillから検索できるようにすれば…。

ただ、Elasticsearchからのデータのロードはシャード数までしか並列化されないため(これはelasticsearch-hadoopでSparkを使う場合なども同じ)、HDFS上のファイルに対して検索を行うのと比べると性能面ではかなりハンデがあるようです。