GoからCloudera Impalaに繋いでみた
近年、ビッグデータというキーワードと共にApache Hadoopが注目されています。
皆さんはHadoopにどんなイメージを持っているでしょうか?何だか難しそうですよね。
ですが、Cloudera Impalaを使えば既存のRDBと同じようにSQLでデータの取り扱いができます。
今回はGoとSQLでCloudera Impalaからデータを取り出すまでの手順を解説したいと思います。
環境
以下の環境で動作確認しました。
| 機能 | OS | IPアドレス |
|---|---|---|
| ODBCクライアント | CentOS6.5 64bit | 192.168.128.2 |
| Cloudera Impala | QuickStart VMs for CDH 5.3.x | 192.168.128.1 |
| ソフト名 | バージョン |
|---|---|
| Go | 1.4.1 |
| unixODBC | 2.2.14-14.el6 |
| Cloudera ODBC Driver for Impala | 2.5.23 |
インストール手順
Installation Guide for Cloudera ODBC 2.5.23 Driver for Impalaを参考にインストールを進めます。
依存パッケージおよびドライバ
まずは依存パッケージとドライバをインストールします。
$ sudo yum install -y cyrus-sasl cyrus-sasl-gssapi cyrus-sasl-plain unixODBC
$ sudo rpm -Uvh https://downloads.cloudera.com/connectors/impala_odbc_2.5.23.1024/Linux/EL6/ClouderaImpalaODBC-2.5.23.1024-1.el6.x86_64.rpm
unixODBCがリンクするライブラリ名がso.1でハードコードされているのでシンボリックリンクを張ります。
これをやっておかないとうまく動きません。
$ sudo ln -sf libodbc.so.2.0.0 /usr/lib64/libodbc.so.1
$ sudo ln -sf libodbcinst.so.2.0.0 /usr/lib64/libodbcinst.so.1
$ ls -l /usr/lib64/libodbc.so* /usr/lib64/libodbcinst.so*
lrwxrwxrwx 1 root root 16 2月 11 15:47 2015 /usr/lib64/libodbc.so -> libodbc.so.2.0.0
lrwxrwxrwx 1 root root 16 2月 11 15:49 2015 /usr/lib64/libodbc.so.1 -> libodbc.so.2.0.0
lrwxrwxrwx 1 root root 16 2月 11 15:47 2015 /usr/lib64/libodbc.so.2 -> libodbc.so.2.0.0
-rwxr-xr-x 1 root root 417720 7月 10 17:15 2014 /usr/lib64/libodbc.so.2.0.0
lrwxrwxrwx 1 root root 20 2月 11 15:47 2015 /usr/lib64/libodbcinst.so -> libodbcinst.so.2.0.0
lrwxrwxrwx 1 root root 20 2月 15 01:56 2015 /usr/lib64/libodbcinst.so.1 -> libodbcinst.so.2.0.0
lrwxrwxrwx 1 root root 20 2月 11 15:47 2015 /usr/lib64/libodbcinst.so.2 -> libodbcinst.so.2.0.0
-rwxr-xr-x 1 root root 68928 7月 10 17:15 2014 /usr/lib64/libodbcinst.so.2.0.0
設定ファイル
設定ファイルは3つあり、それぞれ以下の優先度で配置できます。
- odbc.ini
- 環境変数
ODBCINIのファイル (例: ODBCINI=/etc/odbc.ini) ~/.odbc.ini/etc/odbc.ini
- 環境変数
- odbcinst.ini
- 環境変数
ODBCSYSINIのフォルダにodbcinst.iniを配置 (例: ODBCSYSINI=/etc) ~/.odbcinst.ini/etc/odbcinst.ini
- 環境変数
- cloudera.impalaodbc.ini
- 環境変数
CLOUDERAIMPALAINIのファイル (例: CLOUDERAIMPALAINI=/etc/cloudera.impalaodbc.ini) /opt/cloudera/impalaodbc/lib/64/cloudera.impalaodbc.ini
- 環境変数
今回はすべてconfディレクトリにコピーして環境変数で指定します。
$ mkdir -p work/conf
$ cd work
$ cp /opt/cloudera/impalaodbc/lib/64/cloudera.impalaodbc.ini conf/
$ cp /opt/cloudera/impalaodbc/Setup/odbc.ini conf/
$ cp /opt/cloudera/impalaodbc/Setup/odbcinst.ini conf/
$ export ODBCINI=$PWD/conf/odbc.ini
$ export ODBCSYSINI=$PWD/conf
$ export CLOUDERAIMPALAINI=$PWD/conf/cloudera.impalaodbc.ini
cloudera.impalaodbc.iniについて
ODBCInstLibはunixODBCのlibodbcinst.soを設定します。DriverManagerEncodingはGoのためにUTF-16を設定します。
--- /opt/cloudera/impalaodbc/lib/64/cloudera.impalaodbc.ini 2015-01-19 10:23:00.000000000 +0900
+++ conf/cloudera.impalaodbc.ini 2015-02-15 17:32:47.580673175 +0900
@@ -7,7 +7,7 @@
## - SimbaDM can be used with UTF-8 or UTF-16.
## The DriverUnicodeEncoding setting will cause SimbaDM to run in UTF-8 when set to 2 or UTF-16 when set to 1.
-DriverManagerEncoding=UTF-32
+DriverManagerEncoding=UTF-16
ErrorMessagesPath=/opt/cloudera/impalaodbc/ErrorMessages/
LogLevel=0
LogPath=
@@ -19,10 +19,10 @@
# Generic ODBCInstLib
# iODBC
-ODBCInstLib=libiodbcinst.so
+#ODBCInstLib=libiodbcinst.so
# SimbaDM / unixODBC
-#ODBCInstLib=libodbcinst.so
+ODBCInstLib=libodbcinst.so
# AIX specific ODBCInstLib
# iODBC
odbcinst.iniは変更なしです。
[ODBC Drivers]
Cloudera ODBC Driver for Impala 32-bit=Installed
Cloudera ODBC Driver for Impala 64-bit=Installed
[Cloudera ODBC Driver for Impala 32-bit]
Description=Cloudera ODBC Driver for Impala (32-bit)
Driver=/opt/cloudera/impalaodbc/lib/32/libclouderaimpalaodbc32.so
[Cloudera ODBC Driver for Impala 64-bit]
Description=Cloudera ODBC Driver for Impala (64-bit)
Driver=/opt/cloudera/impalaodbc/lib/64/libclouderaimpalaodbc64.so
### The option below is for using unixODBC when compiled with -DSQL_WCHART_CONVERT.
### Execute 'odbc_config --cflags' to determine if you need to uncomment it.
## IconvEncoding=UCS-4LE
odbc.iniは以下の行を追記します。
DriverUnicodeEncodingはcloudera.impalaodbc.iniの説明に従って1を設定します。
[Impala]
Driver=/opt/cloudera/impalaodbc/lib/64/libclouderaimpalaodbc64.so
HOST=192.168.128.1
PORT=21050
Database=default
DriverUnicodeEncoding=1
動作確認
isqlコマンドでodbc.iniに追加したImpalaを指定してImpalaに接続してみます。
このときだけ環境変数LD_PRELOADの設定が必要なので注意してください。
クエリの実行結果が返ってくれば正常に動作しています。
$ export LD_PRELOAD=/usr/lib64/libodbcinst.so
$ isql Impala -m30
+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
SQL> show databases
+-------------------------------+
| name |
+-------------------------------+
| _impala_builtins |
| default |
+-------------------------------+
SQLRowCount returns -1
2 rows fetched
SQL>
create table, insert, selectを試してみます。
SQL> use default
SQLRowCount returns -1
SQL> create table t (id int, name string)
SQLRowCount returns -1
SQL> show tables
+-------------------------------+
| name |
+-------------------------------+
| t |
+-------------------------------+
SQLRowCount returns -1
1 rows fetched
SQL> insert into t (id, name) values (1, "AAA"), (2, "BBB"), (3, "CCC")
SQLRowCount returns -1
SQL> select id, name from t
+------------+-------------------------------+
| id | name |
+------------+-------------------------------+
| 1 | AAA |
| 2 | BBB |
| 3 | CCC |
+------------+-------------------------------+
SQLRowCount returns -1
3 rows fetched
SQL>
GoとSQLでImpalaに接続
How do I connect Go on Linux to an ODBC Database?の接続文字列とクエリを変更すればそのまま動きます。
// #cgo linux LDFLAGS: -lodbc
package main
import (
"database/sql"
"log"
_ "code.google.com/p/odbc"
)
const (
DSN = "DSN=Impala;" // 接続文字列
QUERY = "select id, name from t" // クエリ
)
func main() {
db, err := sql.Open("odbc", DSN)
if err != nil {
log.Fatal(err)
}
var (
id int
name string
)
rows, err := db.Query(QUERY)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
err := rows.Scan(&id, &name)
if err != nil {
log.Fatal(err)
}
log.Printf("id: %d, name: %sn", id, name)
}
err = rows.Err()
if err != nil {
log.Fatal(err)
}
defer db.Close()
}
実行すると以下のようにクエリ結果が表示されます。
$ go run odbc.go
2015/02/15 17:37:52 id: 1, name: AAA
2015/02/15 17:37:52 id: 2, name: BBB
2015/02/15 17:37:52 id: 3, name: CCC
接続文字列について
接続文字列の指定方法は次のように3つあります。
場合によって使い分けるとよいでしょう。
DSN only
odbc.iniに接続先を設定して、接続文字列ではそのカテゴリ名を設定します。
DSN = "DSN=Impala;"
設定ファイルは次の2つが必要です。
- cloudera.impalaodbc.ini
- odbc.ini
DSN less
odbc.iniは使用せずに、接続文字列で接続先を設定します。
DRIVERはodbcinst.iniのカテゴリ名を設定します。
DSN = "DRIVER={Cloudera ODBC Driver for Impala 64-bit};HOST=192.168.128.1;PORT=21050;Database=sandbox;"
設定ファイルは次の2つが必要です。
- cloudera.impalaodbc.ini
- odbcinst.ini
DSN combine
odbc.iniの定義をテンプレートにして、一部の設定を接続文字列で指定します。
DSN = "DSN=Impala;HOST=192.168.128.1;Database=sandbox;"
設定ファイルはDSN onlyと同様に次の2つが必要です。
- cloudera.impalaodbc.ini
- odbc.ini
まとめ
このようにCloudera ImpalaとODBC Drivers & Connectors for Impalaを組み合わせる事によってHadoopの知識がなくてもSQLでデータを取り出す事ができました。
意外と簡単ではないでしょうか?
また、Apache Hiveよりも格段に速いので、バッチだけではなくフロントエンドから使う事もできそうです。
コメントを残す