Do You PHP はてブロ

Do You PHPはてなからはてブロに移動しました

PHPからCloudera Impalaに繋いでみた

最近ビッグデータ()系のサーバに対してあれこれやってるんですが、ひょんなことから調べる必要が出てきたのでざっくりまとめてみました。
間違ってる所があれば、指摘をお願いします;-)

基本的な環境

  • CentOS 6.2(x86_64)
  • PHP 5.5.11
  • CDH 4.6+Cloudera Impala 1.2.4(別途構築済み)

CDHとは

CDH(Cloudera's Distribution Including Apache Hadoop)は、Cloudera社から提供されているオープンソースApache Hadoopディストリビューションの1つで、Apache HadoopApache HBase、Apache Hive、Apache Pigなどのパッケージが含まれています。
とりあえず、CDHについては以下のページをざっと読むと良いかと。

今回テストでCDH 4.6を使いましたが、最近CDH5がリリースされたようです。

また、Cloudera社のサイトからVMイメージ(Cloudera QuickStart VM)もダウンロードできます。

Cloudera Impalaとは

Cloudera Impalaは、CDHと同様、Cloudera社から提供されているHiveの上位互換のSQLが利用できる分散クエリエンジンです。
Impalaについては以下のページをざっと読むと良いかと。

CDH 5からCDHに組み込まれるようになったようです。

PHPからの接続

PHPからCloudera Impalaへの接続方法は、以下の2通りがあるようです。

ODBC経由でCloudera Impalaに接続する

Cloudera社からCloudera Impala用のODBCドライバがダウンロードできますが、それだけだとPHPから利用できないので、今回はドライバマネージャとしてiODBCを使い、Cloudera ODBC Driver 2.5 for Impalaで接続してみました。

1. iODBCのインストール

ダウンロード後、いつも通りのconfigure/make/make installでOKです。

$ wget http://downloads.sourceforge.net/project/iodbc/iodbc/3.52.9/libiodbc-3.52.9.tar.gz
$ sudo tar zxf libiodbc-3.52.9.tar.gz
$ cd libiodbc-3.52.9/
$ configure
$ make
$ sudo make install
$ 
2. Cloudera ODBC Driver 2.5 for Impalaのインストール

Cloudera ODBC Driver 2.5 for Impalaの方ですが、rpm形式で提供されているので、rpmコマンドでインストールします。cyrus-sasl系やopenssl系など依存関係にあるパッケージは別途yumなどでインストールしておいてください。

$ sudo rpm -ivh ClouderaImpalaODBC-2.5.13.1013-1.el6.x86_64.rpm
$ 

また、ODBC接続に必要なiniファイルもrpmパッケージに含まれていますので、確認しておきます。

$ ls /opt/cloudera/impalaodbc/Setup/
cloudera.impalaodbc.ini  odbc.ini  odbcinst.ini
$ 
3. ODBCの設定

基本的な流れにはインストールガイド(pdf)にある通りです。
今回はテスト用ディレクトリを作ってそこにiniファイルを配置してみます。

$ mkdir test
$ cd test/
$ cp /opt/cloudera/impalaodbc/Setup/*.ini .
$

デフォルトだと、カレントディレクトリにある各iniファイルを読みに行かないので、環境変数を設定しておきます。iniファイルの検索順序の詳細については、インストールガイド(pdf)を参照してください(p.10の終わり頃から)。

$ export ODBCINI=`pwd`/odbc.ini # フルパスの必要あり
$ export ODBCSYSINI=`pwd`/
$ export SIMBAINI=`pwd`/cloudera.impalaodbc.ini # フルパスの必要あり
$

続いて、接続用のDSNを定義します。コピーしたodbc.iniにも定義されていますので、それを使っても良いと思います。最低限、

  • HOST(Cloudera Impalaが稼働しているサーバのIPアドレスもしくはホスト名)
  • PORT(ODBC接続の場合は21050)
  • Driver(libclouderaimpalaodbc64.soへのフルパス)

を定義しておけばOKです。まあ、接続時に指定してもいいんですけどね。。。今回は以下の内容をodbc.iniの最後に追加しました。

[Impala]
HOST=localhost
PORT=21050
Driver=/opt/cloudera/impalaodbc/lib/64/libclouderaimpalaodbc64.so
4. LD_LIBRARY_PATHの設定

ドライバマネージャであるiODBCとODBCドライバであるCloudera ODBC Driver 2.5 for Impalaの各ライブラリへのパスをLD_LIBRARY_PATHに設定します。

$ export LD_LIBRARY_PATH=/usr/local/lib:/opt/cloudera/impalaodbc/lib/64/
$ 
5. PHPスクリプトを作成

基本的にはODBC関数を使ったコードであれば良いはずです。今回は次のようなテーブル一覧を出力するスクリプト(test.php)を作ってみました。

<?php
$connection = odbc_connect("DSN=Impala;", '', '');
$query = "show tables";
$rs = odbc_exec($connection, $query);
while ($row = odbc_fetch_array($rs)) {
    echo (isset($row['name']) ? $row['name'] : null) . PHP_EOL;
}
odbc_free_result($rs);
odbc_close($connection);

PDO ODBCの場合は次のような感じで。

<?php
try {
    $dbh = new PDO('odbc:DSN=Impala;', '', '');
    foreach($dbh->query('show tables') as $row) {
        echo (isset($row['name']) ? $row['name'] : null) . PHP_EOL;
    }
    $dbh = null;
} catch (PDOException $e) {
    die($e->getMessage());
}
6. 実行してみる

PHPodbc拡張が組み込まれていることを確認して実行します。今回はconfigure時に

--with-iodbc=shared --with-pdo-odbc=shared,iODBC

を付けてbuildしたPHPを使いました。これで作成したテーブル一覧が表示されればOKです。

$ /path/to/php -ddate.timezone=Asia/Tokyo -dextension=/path/to/odbc.so test.php
  :
$

PDO ODBCの場合。

$ /path/to/php -ddate.timezone=Asia/Tokyo -dextension=/path/to/pdo.so -dextension=/path/to/pdo_odbc.so test.php
  :
$

あとは、SELECT文をいろいろ試してみましょう:-)

ThriftでCloudera Impalaに接続する

先日のHBaseへの接続の際にも使用したThriftですが、Cloudera Impalaにも接続できます。ポート番号は21000です。
GitHubにいくつかライブラリが公開されているようなので、今回は次の2種類を試してみました。

a. PHPphp_impala_pharでCloudera Impalaに接続する

まずは、コード一式をダウンロードして展開します。

$ wget https://github.com/rmcfrazier/php_impala_phar/archive/master.zip -O php_impara_phar-master.zip
$ unzip php_impara_phar-master.zip
$ cd php_impara_phar-master/
$ 

直下にtest.phpがありますので、ホスト名の部分('<impala_host>')を適宜修正して実行します。以下の様な内容が出力されればOKです。

$ perl -i -p -s -e "s/<impala_host>/localhost/g" test.php
$ /path/to/php -ddate.timezone=Asia/Tokyo test.php
object(Results)#10 (5) {
  ["ready"]=>
  bool(true)
  ["columns"]=>
  array(1) {
    [0]=>
    string(6) "string"
  }
  ["data"]=>
     :
  }
  ["start_row"]=>
  int(0)
  ["has_more"]=>
  bool(false)
}
$ 
b. PHPphp-impalaでCloudera Impalaに接続する

php_impara_pharと同様、コード一式をダウンロードして展開します。

$ cd ../
$ wget https://github.com/RJMetrics/php-impala/archive/master.zip -O php-impala-master.zip
$ unzip php-impala-master.zip
$ cd php-impala-master/
$ 

やはり直下にtest.phpがありますので、ホスト名の部分(127.0.0.1)とポート番号(50000)を適宜修正して実行します。同様に、以下の様な内容が出力されればOKです。なお、返されるオブジェクトの名前空間が、php_impara_pharとは異なることに注意です。

$ perl -i -p -s -e "s/50000/21000/g" test.php
$ /path/to/php -ddate.timezone=Asia/Tokyo test.php
object(Beeswax\Results)#10 (5) {
  ["ready"]=>
  bool(true)
  ["columns"]=>
  array(1) {
    [0]=>
    string(6) "string"
  }
  ["data"]=>
     :
  }
  ["start_row"]=>
  int(0)
  ["has_more"]=>
  bool(false)
}
$ 

thriftファイルからPHPコードを出力したい

php-impalaにはthriftファイルが含まれています(zipファイルを展開した直下にthriftディレクトリ)ので、Thriftに食わせてPHPコードを生成することができます。手順はhttp://d.hatena.ne.jp/shimooka/20130828/1377686595にもありますが、以下の様な感じになります。

$ for fn in php-impala-master/thrift/*.thrift; do thrift --gen php $fn; done
$ 

直下にgen-phpディレクトリが作成されますので、中身を確認します。

まとめ

またまた「繋げられましたよー」で終わっちゃいます。。。(汗)
Cloudera ImpalaはUPDATEやDELETEなどデータを更新する機能はないので使いどころが問題になってくると思いますが、HBaseと異なり、SQLっぽいクエリ(ほぼSQL)を投げられますのでHBaseよりは親近感がわきますね(笑)。また、100万件レベルの検索でもかなりパフォーマンスが良いです(サーバ構成等に依存するとは思いますが)。データがもうちょっと溜まってきた時(億単位以上)にどうなるかは見てみたいですね。
PHPからも意外と手軽に接続できますし、SQLを投げられる=ORM使ってモデルクラスやアクセスクラスなどの自動生成も可能じゃないかと思います。