HiveコマンドをHadoopクライアントを利用せずに実行するには、HiveServer2をセットアップしHiveServer2を経由してHiveHadoopクラスター上でMapReduceジョブを実行します。
HiveServer2は名前の通りHiveServerのバージョン2でApache Hive 0.11から導入されました。
HiveServer2のクライアントは、以下のようにCLIのBeelineの他に専用のJDBCやODBCドライバを利用するアプリケーションになります。
HiveServer2は、HiveQLを受け取るとMapReduceに変換してHadoopクラスターに実行を要求します。
この図は、ClouderaのブログHow HiveServer2 Brings Security and Concurrency to Apache Hiveを参考にしています。
BeelineはJDBCのアプリなので厳密には構成がちょっと違いますが、HiveServer2の利用イメージはこんな感じです。
以下、Hive CLIがHadoopクラスタに対して実行可能な環境に、HiveServer2を追加し、JDBCを利用するBeeline CLIとPythonのドライバを利用したサンプルの実行確認まで手順をまとめて行きます。
OSはUbuntu 12.04、ディストリビューションはCDH5を利用しています。
HiveServer2のインストール
CDH5のapt-getキーを追加後、hive-server2をインストールします。
$ wget http://archive.cloudera.com/cdh5/one-click-install/precise/amd64/cdh5-repository_1.0_all.deb
$ sudo dpkg -i cdh5-repository_1.0_all.deb
$ sudo apt-get update
$ sudo apt-get install hive-server2
参考: Installing Hive
HiveServer2は平行接続のハンドリングにZooKeeperサーバーを使用します。
Installing the ZooKeeper Packagesに従って、ZooKeeperサーバーをインストールして起動します。
$ sudo apt-get install zookeeper-server
$ mkdir -p /var/lib/zookeeper
$ chown -R zookeeper /var/lib/zookeeper/
$ sudo service zookeeper-server init
$ sudo service zookeeper-server start
Zookeeperをインストールしたら、Configuring HiveServer2に従いZookeeperの設定をhive-site.xmlに追加します。
<!-- /etc/hive/conf/hive-site.xml -->
...
<property>
<name>hive.support.concurrency</name>
<description>Enable Hive's Table Lock Manager Service</description>
<value>true</value>
</property>
<property>
<name>hive.zookeeper.quorum</name>
<description>Zookeeper quorum used by Hive's Table Lock Manager</description>
<value>localhost</value>
</property>
...
設定を有効にします。
$ sudo service hive-server2 restart
HiveServer2にbeelineで接続確認してみます。
ここまでの手順では、embeddedモードでのみ接続が可能です。
$ beeline -u jdbc:hive2://
...
Connected to: Apache Hive (version 0.13.1-cdh5.2.0)
Driver: Hive JDBC (version 0.13.1-cdh5.2.0)
Transaction isolation: TRANSACTION_REPEATABLE_READ
Beeline version 0.13.1-cdh5.2.0 by Apache Hive
0: jdbc:hive2://> show tables;
...
+-----------+--+
| tab_name |
+-----------+--+
| u_data |
+-----------+--+
1 row selected (0.793 seconds)
...
MetaStoreのリポジトリデータベースがデフォルトのDerbyの場合、同時接続を制御できないため、HiveServer2はリモート接続を許可しません。
つまり10000ポートは閉じたままになっています。
リモート接続を許可するためには、MetastoreにMySQLなどのDBMSを指定する必要がります。
MetaStoreのリポジトリをMySQLに設定する
MetaStoreのセットアップ方法は、Configuring the Hive Metastoreに詳しい説明があります。
以下の手順の例では、リポジトリにMySQLを利用するようにセットアップしていきます。
また、MySQLはHiveServer2と同じマシンにインストールしています。
$ sudo apt-get install mysql-server
$ sudo apt-get install libmysql-java
$ ln -s /usr/share/java/mysql-connector-java.jar /usr/lib/hive/lib/mysql-connector.java.jar
ドキュメントに記述されているjarファイルの名前が異なっているので注意
リポジトリ用のデータベースを作成して、テーブルを作成するSQLを実行します。
$ mysql -u root -p
mysql> create database metastore;
mysql> USE metastore;
mysql> SOURCE /usr/lib/hive/scripts/metastore/upgrade/mysql/hive-schema-0.13.0.mysql.sql;
MetaStore用のMySQLへの接続ユーザーを作成します。
$ mysql -u root -p
mysql> USE metastore
mysql> CREATE USER 'hive'@'localhost' IDENTIFIED BY 'hive';
mysql> REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'hive'@'localhost';
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,LOCK TABLES,EXECUTE ON metastore.* TO 'hive'@'localhost';
mysql> FLUSH PRIVILEGES;
mysql> quit;
MetaStoreのリポジトリはMySQLを利用するように、hive-site.xmlの設定を変更します。
~~xml
設定を有効にします。
~~~bash
$ sudo service hive-server2 restart
beelineで確認してみます。
$ beeline
beeline> !connect jdbc:hive2://localhost:10000 hive hive org.apache.hive.jdbc.HiveDriver
Connecting to jdbc:hive2://localhost:10000
Connected to: Apache Hive (version 0.13.1-cdh5.2.0)
Driver: Hive JDBC (version 0.13.1-cdh5.2.0)
Transaction isolation: TRANSACTION_REPEATABLE_READ
0: jdbc:hive2://localhost:10000> show tables;
+-----------+--+
| tab_name |
+-----------+--+
+-----------+--+
No rows selected (0.988 seconds)
MetaStoreのリポジトリが変更されたのでテーブルが無い状態になっていることが確認できます。
Pyhonからのアクセス
Setting Up HiveServer2 – Apache Hive – Apache Software FoundationにPythonドライバを利用したHiveServer2へのアクセスの記述を見つけたので、そちらも試してみます。
Hiveドライバ pyhs2 をインストールします。
$ sudo apt-get install -y python-dev libldap2-dev libsasl2-dev libssl-dev
$ pip install pyhs2
# select.py
import pyhs2
with pyhs2.connect(host='localhost',
port=10000,
authMechanism="PLAIN",
user='hive',
password='hive',
database='default') as conn:
with conn.cursor() as cur:
#Show databases
print cur.getDatabases()
#Execute query
cur.execute("select * from movie_lens limit 10")
#Return column info from query
print cur.getSchema()
#Fetch table results
for i in cur.fetch():
print i
MetaStoreを新しく設定したばかりなのでテーブルが一つもありませんので、テーブルを「movie_lens」追加してデータをロードしておきます。
(データの準備の手順は、こちらの記事の「Cloudera版のHiveをインストールしてリモートクラスタ上でジョブを実行する」を参照下さい)
プログラムを実行してみます。
$ python select.py
[['default', '']]
[{'comment': None, 'columnName': 'movie_lens.userid', 'type': 'INT_TYPE'}, {'comment': None, 'columnName': 'movie_lens.movieid', 'type': 'INT_TYPE'}, {'comment': None, 'columnName': 'movie_lens.rating', 'type': 'INT_TYPE'}, {'comment': None, 'columnName': 'movie_lens.unixtime', 'type': 'STRING_TYPE'}]
[196, 242, 3, '881250949']
[186, 302, 3, '891717742']
[22, 377, 1, '878887116']
[244, 51, 2, '880606923']
[166, 346, 1, '886397596']
[298, 474, 4, '884182806']
[115, 265, 2, '881171488']
[253, 465, 5, '891628467']
[305, 451, 3, '886324817']
[6, 86, 3, '883603013']
10件レコードを取得できました。
補足: MetaStoreサービスのセットアップ
上記の設定は、Configuring the Hive Metastoreに説明のある「Metastore Deployment Modes」のうち「Local Mode」にあたります。
「Remote Mode」の構成にするには、MetaStoreをサービスとして起動し、HiveがサービスのMetaStoreへアクセスするように設定を変更します。
MetaStoreサービスを利用する場合は、以下の手順でセットアップできます。
MetaStoreサーバーのインストール
$ sudo apt-get install hive-metastore
参考: Installing Hive
MetaStoreサーバーを参照するようにhive-site.xmlを変更します。
<!-- /etc/hive/conf/hive-site.xml -->
<property>
<name>hive.metastore.uris</name>
<value>thrift://127.0.0.1:9083</value>
<description>IP address (or fully-qualified domain name) and port of the metastore host</description>
</property>
設定を有効にします。
$ sudo service hive-server2 restart
補足2: トラブルシューティング – リモート接続ができない
MetaStoreがデフォルトのDerbyの場合はリモート接続ができません。
ログには、以下のエラーが出力されています。
# /var/log/hive/hive-server2.log
2014-11-29 14:29:45,960 ERROR [BoneCP-pool-watch-thread]: bonecp.PoolWatchThread (PoolWatchThread.java:fillConnections(118)) - Error in trying to obtain a connection. Retrying in 7000ms
java.sql.SQLException: A read-only user or a user in a read-only database is not permitted to disable read-only mode on a connection.
at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.TransactionResourceImpl.handleException(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedConnection.handleException(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedConnection.setReadOnly(Unknown Source)
at com.jolbox.bonecp.ConnectionHandle.setReadOnly(ConnectionHandle.java:1324)
at com.jolbox.bonecp.ConnectionHandle.<init>(ConnectionHandle.java:262)
at com.jolbox.bonecp.PoolWatchThread.fillConnections(PoolWatchThread.java:115)
at com.jolbox.bonecp.PoolWatchThread.run(PoolWatchThread.java:82)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.sql.SQLException: A read-only user or a user in a read-only database is not permitted to disable read-only mode on a connection.
at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(Unknown Source)
... 13 more
Caused by: ERROR 25505: A read-only user or a user in a read-only database is not permitted to disable read-only mode on a connection.
at org.apache.derby.iapi.error.StandardException.newException(Unknown Source)
at org.apache.derby.impl.sql.conn.GenericAuthorizer.setReadOnlyConnection(Unknown Source)
at org.apache.derby.impl.sql.conn.GenericLanguageConnectionContext.setReadOnly(Unknown Source)
... 8 more
Hive with Derby to accomodate Multiple User – Grokbase
補足3: 参考
http://www.slideshare.net/schubertzhang/hiveserver2