CLOVER🍀

That was when it all began.

Ubuntu Linux 18.04 LTSにApache DrillをEmbedded Modeでインストールして、CSVファイルを読んで遊ぶ

Apache Drill?

Apache Drillとは、さまざまなデータソースに対してクエリを実行できるソフトウェアです。

Apache Drill - Schema-free SQL for Hadoop, NoSQL and Cloud Storage

Apache Drill を利用した実データの分析

GoogleのDremelにインスパイアされて、開発されたということらしいです。

Dremel: Interactive Analysis of Web-Scale Datasets – Google AI

どういうデータソースにアクセスできるかというと、

Connect a Data Source Introduction - Apache Drill

f:id:Kazuhira:20191012215550p:plain

と、いったように、以下のようなデータソースが対象です。

また、ファイルを読む場合、対応するファイルフォーマットとしてはこちら。

Data Sources and File Formats Introduction - Apache Drill

f:id:Kazuhira:20191012210018p:plain

今回、このApache Drillを使って、ローカルファイルシステム上にあるCSVファイルに対してクエリを実行してみましょう。

環境

今回の環境は、こちら。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.3 LTS
Release:    18.04
Codename:   bionic


$ java -version
openjdk version "1.8.0_222"
OpenJDK Runtime Environment (build 1.8.0_222-8u222-b10-1ubuntu1~18.04.1-b10)
OpenJDK 64-Bit Server VM (build 25.222-b10, mixed mode)

Apache Drillの実行には、Oracle JDK 8またはOpenJDK 8が必要です。

以下を読み進めながら、インストール。

Apache Drillには2つの実行モードがあり、スタンドアロンで動かすのをEmbedded Mode、分散環境上で動作させるのを
Distributed Modeと呼びます。

今回は、スタンドアロンで動かすのでEmbedded Modeでインストールします。

Install Drill Introduction - Apache Drill

Embedded Mode Prerequisites - Apache Drill

Installing Drill on Linux and Mac OS X - Apache Drill

といっても、tar.gzファイルをダウンロードして解凍すればおしまいです。

$ wget https://www-us.apache.org/dist/drill/drill-1.16.0/apache-drill-1.16.0.tar.gz
$ tar xf apache-drill-1.16.0.tar.gz
$ cd apache-drill-1.16.0

起動。

Starting Drill on Linux and Mac OS X - Apache Drill

$ bin/drill-embedded
Apache Drill 1.16.0
"Think different, think Drill."
apache drill> 

そのまま、インタラクティブシェルが起動し、クエリを実行することができます。

また、この時にWeb UIも起動しています。

Starting the Web UI - Apache Drill

http://localhost:8047/」にアクセスしてみると、Web UIへアクセスできます。今回は、このWeb UIを中心に使っていきましょう。

f:id:Kazuhira:20191012205002p:plain

CSVファイルにクエリを投げてみる

プレーンテキストにクエリを投げるためのドキュメントは、こちら。

Querying Plain Text Files - Apache Drill

CSVに対してクエリを実行するサンプルがあるので、実行してみましょう。こんなファイルを用意。

plays.csv

1599,As You Like It
1601,Twelfth Night
1594,Comedy of Errors
1595,Romeo and Juliet
1596,The Merchant of Venice
1610,The Tempest
1599,Hamlet

「Query」を選んで、以下のクエリを実行してみます。

select * from dfs.`/path/to/plays.csv`

f:id:Kazuhira:20191012214714p:plain

結果は、こんな感じ。

f:id:Kazuhira:20191012214742p:plain

「Query Profile」を押すと、クエリの実行計画を見たり、クエリを修正して再度実行させたりできます。

f:id:Kazuhira:20191012214910p:plain

ただ、「Query Profile」を押すと、別タブが開くんですよね…。それにクエリを間違ったりすると修正できなくなったりするので、
UIとしてはもうちょっと良いものが欲しいかもですね。

同じクエリを、シェルで実行した場合はこうなります。

apache drill> select * from dfs.`/path/to/plays.csv`;
+-----------------------------------+
|              columns              |
+-----------------------------------+
| ["1599","As You Like It"]         |
| ["1601","Twelfth Night"]          |
| ["1594","Comedy of Errors"]       |
| ["1595","Romeo and Juliet"]       |
| ["1596","The Merchant of Venice"] |
| ["1610","The Tempest"]            |
| ["1599","Hamlet"]                 |
+-----------------------------------+
7 rows selected (0.112 seconds)

ところで、クエリを実行した時にファイルパスの前に書いていた

select * from dfs.`/path/to/plays.csv`

この「dfs」というのはなんでしょう。

Web UIから、「Storage」というものを選んでみます。

f:id:Kazuhira:20191012220202p:plain

ここに載っている「dfs」というやつですね。

これは、File System Storageです。

File System Storage Plugin - Apache Drill

設定を見ると、ローカルファイルシステムを対象にしています。from句に書いたファイルパスは、「workspace」と呼ばれるものからの
相対パスで指定するようです。今回は「/」がワークスペースに入っていますが。

{
  "type": "file",
  "connection": "file:///",
  "config": null,
  "workspaces": {
    "tmp": {
      "location": "/tmp",
      "writable": true,
      "defaultInputFormat": null,
      "allowAccessOutsideWorkspace": false
    },
    "root": {
      "location": "/",
      "writable": false,
      "defaultInputFormat": null,
      "allowAccessOutsideWorkspace": false
    }
  },

f:id:Kazuhira:20191012220136p:plain

ここで、File System Storageの設定を変えてみることを考えてみます。

例えば、先ほどのクエリの実行結果は、列が「columns」というようにまとめられていましたが、以下のように「as」を使うことで
列に別名を与えることができます。まあ、通常のSQLの話ですね。

select columns[0] as c1, columns[1] as c2 from dfs.`/path/to/plays.csv`

これで、列に別名を与えて実行できます。

f:id:Kazuhira:20191012221249p:plain

このようにクエリで列名を与えるのではなく、CSVファイルの中にヘッダーとして列名を書いていきたいと思います。

plays.csv

c1,c2
1599,As You Like It
1601,Twelfth Night
1594,Comedy of Errors
1595,Romeo and Juliet
1596,The Merchant of Venice
1610,The Tempest
1599,Hamlet

列名は、c1、c2としました。

このまま先ほどのクエリを実行すると、追加した列名は単なる値として扱われます。

f:id:Kazuhira:20191012224941p:plain

ここで、CSVファイルにヘッダーがあることを指定します。これは、File System Storageプラグインの設定です。

    "csv": {
      "type": "text",
      "extensions": [
        "csv"
      ],
      "delimiter": ",",
      "extractHeader": true
    },

dfsファイルストレージの設定を、これで保存。

設定項目は、こちらに書かれています。

Text Files: CSV, TSV, PSV - Apache Drill

ところで、File System Storageプラグインの設定を見ると、拡張子「csvh」であればヘッダー行ありのCSVとして認識してくれるようです。
ケースによっては、こちらを使っても良いのかもしれません。

    "csvh": {
      "type": "text",
      "extensions": [
        "csvh"
      ],
      "extractHeader": true,
      "delimiter": ","
    },

Apache Drillでは、ファイルの拡張子とフォーマットが紐づくようですね。

クエリの実行結果。

f:id:Kazuhira:20191012225107p:plain

ところで、デリミタなどの指定は可能なのですが、読み込むファイルのエンコーディングの指定はありません。
UTF-8でファイルが書かれていることが、前提になっているみたいですね。

2つのファイルをJOINしてみる

最後に、2つのCSVファイルをJOINしてみましょう。

以下のような2つのファイルを用意。
books.csv

isbn,title,price,category_id
978-4297100339,Docker/Kubernetes 実践コンテナ開発入門,3718,1
978-4798134888,詳解UNIXプログラミング 第3版,9130,2
978-4798053776,アプリケーションエンジニアのためのApache Spark入門,3740,3
978-4798152370,Apache Kafka 分散メッセージングシステムの構築と活用,3960,3
978-4774196077,Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識,3278,2

categories.csv

id,name
1,Docker
2,Linux
3,ビッグデータ

この2つのファイルを、JOINしてみます。

select book.isbn, book.title, book.price, category.name as category_name
from dfs.`/path/to/books.csv` as book
inner join dfs.`/path/to/categories.csv` as category
on book.category_id = category.id
order by book.price asc

結果。

f:id:Kazuhira:20191013011600p:plain

OKそうです。

まとめ

今回は、Apache DrillをEmbedded Modeでインストールして、CSVファイルを読み、クエリを実行するところまでを試してみました。

他にもJSONファイルが読めたり、RDBMSAmazon S3をデータソースにしたりといろいろできるのですが、それまたの機会に。