- 2015.02.19
- 技術ブログ
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を参考にインストールを進めます。
依存パッケージおよびドライバ
まずは依存パッケージとドライバをインストールします。
1 2 3 |
$ 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
でハードコードされているのでシンボリックリンクを張ります。
これをやっておかないとうまく動きません。
1 2 3 4 5 6 7 8 9 10 11 12 |
$ 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ディレクトリにコピーして環境変数で指定します。
1 2 3 4 5 6 7 8 9 |
$ 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
を設定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
--- /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は変更なしです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
[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
を設定します。
1 2 3 4 5 6 7 |
[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
の設定が必要なので注意してください。
クエリの実行結果が返ってくれば正常に動作しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
$ 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
を試してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
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?の接続文字列とクエリを変更すればそのまま動きます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
// #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() } |
実行すると以下のようにクエリ結果が表示されます。
1 2 3 4 5 |
$ 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に接続先を設定して、接続文字列ではそのカテゴリ名を設定します。
1 2 |
DSN = "DSN=Impala;" |
設定ファイルは次の2つが必要です。
- cloudera.impalaodbc.ini
- odbc.ini
DSN less
odbc.iniは使用せずに、接続文字列で接続先を設定します。
DRIVER
はodbcinst.iniのカテゴリ名を設定します。
1 2 |
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の定義をテンプレートにして、一部の設定を接続文字列で指定します。
1 2 |
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よりも格段に速いので、バッチだけではなくフロントエンドから使う事もできそうです。