引き続きビッグデータ関連のミドルウェアを使った開発ばかりしてます。
もうすぐスーパーファミコンですね。
PHPを使ったビッグデータへのアプローチ方法などを話すことが多いですが、
今回は登壇時に例に挙げることも多いPrestoとPHPからの利用方法について紹介します。
Prestoって何?
PrestoはFacebookで開発された分散SQLクエリエンジンで、
Webアプリケーションにとってはあまり馴染みがないかもしれませんが、
大規模なデータに対してインタラクティブに結果を返せるようになっていて、
Apache HiveやApache Impalaと同じようなものと考えるのが早いでしょう。
ただWebアプリケーションエンジニアに嬉しいのは、
異なるデータベース(RDBMS)やデータストレージを結合して集計ができるという、
管理ツールや分散したデータベースを跨ぐ処理へのアプローチなど、活用できる場面が多くあります。
(Re:dashなどもあります)
更なる詳細については多くの記事や解説がありますので、そちらを参照してください。
当然、利用ケースや場面によってはSparkやImpalaを利用した方が高速な場合もあり、
構成によっては、Kuduの方がよりフィットする場合もあると思います
(HDFSに格納されていてHBaseも使ってるぜ!みたいなケースだったり)
今回はPHPのアプリケーションで想定できるケースでどう使うか、
実際にどう組み込むかをやってみましょう。
異なるデータベースのjoinは、PostgreSQLのFDWやSQLServerのOPENQUERYなどもあります
Prestoをうごかす
現時点の最新は0.184ですので、マニュアルに沿ってインストールします。
$ wget https://repo1.maven.org/maven2/com/facebook/presto/presto-server/0.184/presto-server-0.184.tar.gz
解凍後に設置するだけで済みますが、
Prestoの設定や、接続したいデータベースの情報や記載するために
解凍したprestoのディレクトリに etc
ディレクトリを作成します。
詳細はマニュアルに記載されていますので、ささっと初期設定をやってしまいます。
2.1. Deploying Presto — Presto 0.184 Documentation
launcherのrunを実行し、問題がなければstartなどで起動させます。
$ bin/launcher run
起動して、configで設定した discovery.uri
にアクセスすると下記の画面が表示されます。
接続先を追加する
次にMySQLに接続するように設定を追加します。
追加したetcディレクトリに、更に catalog
ディレクトリを追加します。
各データベースへの接続情報はカタログに置いていきます。
MySQLのテーブル例
テーブルは下記のようなものを作ったとします。 (databaseはtestingとします)
CREATE TABLE `tests` ( `test_id` int(11) unsigned NOT NULL AUTO_INCREMENT, `test_name` varchar(85) NOT NULL DEFAULT '', `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`test_id`), UNIQUE KEY `UIDX_TESTS_NAME` (`test_name`), KEY `IDX_TESTS` (`test_name`,`test_id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
データは適当に入れておきます
INSERT INTO tests(test_name) VALUE('presto');
mysqlのcatalogは次の形式で記述します。
connector.name=mysql # コネクタのドライバ指定になるので、mysqlのままです connection-url=jdbc:mysql://example.net:3306 # 以下は利用環境に合わせて指定します connection-user=root connection-password=secret
接続時にファイル名をカタログ名として利用しますので、
わかりやすい名前にしておきましょう。
仮にここでは etc/catalog/my_tests.properties
として進めます。
Redisの例
次にRedisです。
せっかくなので、Redisのdatabaseをデフォルトではなく10を指定したとして設定を記述します。
10を利用するときは次の通りです
$ redis-cli 127.0.0.1:6379> SELECT 10 OK 127.0.0.1:6379[10]>
*IPなどは環境に合わせてください
Redisのcatalogに記述する項目は、先ほどのMySQLとは少し違います
5.14. Redis Connector — Presto 0.184 Documentation
今回はRedisの一番の基本のStringを主として、次のように記述します。
connector.name=redis redis.table-names=test.string redis.nodes=127.0.0.1:6379 redis.database-index=10
仮にここでは etc/catalog/red_tests.properties
として進めます。
ここでも適当にデータを入れておきます。
127.0.0.1:6379[10]> SET presto awesome OK 127.0.0.1:6379[10]> GET presto "awesome"
これで準備が整いました。 prestoから接続できるか確認してみます。
Presto Command Line Interface
最初にインストールしたUIからはなにもできません。
CLIをダウンロードします。
2.2. Command Line Interface — Presto 0.184 Documentation
presto
で利用できるようにjarのファイル名を変更します
$ wget https://repo1.maven.org/maven2/com/facebook/presto/presto-cli/0.184/presto-cli-0.184-executable.jar $ mv presto-cli-0.184-executable.jar presto $ chmod 755 presto
–serverにはprestoのconfigで設定した discovery.uri
を指定します。
$ ./presto --server 127.0.0.1:8080 presto>
コンソールに入ったら現在時刻でも取得して動作確認しておきましょう。
presto> SELECT NOW(); _col0 ------------------------------------ 2017-09-15 04:29:51.689 Asia/Tokyo (1 row) Query 20170914_192951_00000_bv9h4, FINISHED, 1 node Splits: 17 total, 17 done (100.00%) 0:01 [0 rows, 0B] [0 rows/s, 0B/s]
ばっちりです
MySQL, Redisに接続する
事前に記述した接続先に接続してクエリを投げてみましょう *launcherのrestartは忘れずに
MySQL
事前に用意した接続先にクエリを投げます
<catalog名>.<データベース名>.<テーブル名>で指定します。
presto> SELECT * FROM my_tests.testing.tests; test_id | test_name | created_at ---------+-----------+------------------------- 1 | presto | 2017-09-15 03:49:30.000 (1 row) Query 20170914_194006_00007_ijqj3, FINISHED, 1 node Splits: 17 total, 17 done (100.00%) 0:01 [1 rows, 0B] [1 rows/s, 0B/s]
prestoから結果が取得できているのが見えます。
エラーが出る場合はSCHEMASが見えるか、など確認しましょう。
presto> SHOW SCHEMAS FROM my_tests; Schema -------------------- information_schema testing (2 rows)
Redis
MySQLと問い合わせ方法は同じです。
redis.table-names
で指定した名前を使って、<カタログ名>.<namesで記述した名前>を指定します。
マニュアルにもある通り、Redisは内部的なカラムとしていくつかあります。
Column name | Type | Description |
---|---|---|
_key | VARCHAR | Redis key. |
_value | VARCHAR | Redis value corresponding to the key. |
*一部抜粋
今はkey, valueをSELECT 区に入れてみます。
presto> SELECT _key, _value FROM red_tests.test.string; _key | _value --------+--------- presto | awesome (1 row) Query 20170914_194457_00012_ijqj3, FINISHED, 1 node Splits: 17 total, 17 done (100.00%) 0:00 [1 rows, 7B] [12 rows/s, 90B/s]
先ほど挿入した値が取得できました。
MySQL Redis JOIN
ことなるデータストレージを結合して検索してみましょう。
presto> SELECT _key, _value, test_id, test_name, created_at FROM my_tests.testing.tests AS myttt -> INNER JOIN red_tests.test.string AS redttt ON redttt._key = myttt.test_name -> WHERE myttt.test_name = 'presto'; _key | _value | test_id | test_name | created_at --------+---------+---------+-----------+------------------------- presto | awesome | 1 | presto | 2017-09-15 03:49:30.000 (1 row) Query 20170914_195255_00018_ijqj3, FINISHED, 1 node Splits: 66 total, 66 done (100.00%) 0:00 [2 rows, 7B] [4 rows/s, 15B/s]
当然存在しない値を指定すると、0rowsとなります。
presto> SELECT _key, _value, test_id, test_name, created_at FROM my_tests.testing.tests AS myttt -> INNER JOIN red_tests.test.string AS redttt ON redttt._key = myttt.test_name -> WHERE myttt.test_name = 'ytake'; _key | _value | test_id | test_name | created_at ------+--------+---------+-----------+------------ (0 rows) Query 20170914_195337_00020_ijqj3, FINISHED, 1 node Splits: 66 total, 66 done (100.00%) 0:00 [1 rows, 7B] [2 rows/s, 15B/s]
次回は、早速PHPから利用し、もう少しだけ複雑にしてみます。