mariadb
apache-drill
性能
ulgeekDay 16

Apache Drillの性能を測ってみた

はじめに

Apache DrillはスキーマフリーのSQLクエリエンジンです。
Apache Drillがどのぐらいの性能が出るのか軽く測定してみたので、測定内容と活用シーンに関する所感をご紹介します。

Apache Drillとは

端的に言えば、HDFS上のファイル(CSV・JSON)やNoSQL(HBase・MongoDB)等に対してSQLを発行できるものです。
特徴としては、非構造化データに対して直接クエリを発行できること、クエリはANSI SQL準拠であることが挙げられます。
詳しくは公式ドキュメントを参照してみてください。

やってみたこと

  • DrillでCSVファイルに対してSQLを実行したときの性能を測定する。
  • 比較対象として同じデータをMariaDBにも投入し、同じSQLを実行したときの性能も測定する。

環境

ローカルPC内にVirtualBoxを導入し、仮想マシンを2台立てて測定しました。
ローカルPCのスペックは以下の通りです。

  • CPU:Core i7-6500U CPU @ 2.50GHz 2.59GHz
  • MEM:16GB

各仮想マシンのリソース割り当ては以下の通りです。

  • CPU:2CPU / アクセラレーション有効化
  • MEM:6144MB

Drillの導入手順については詳しくご紹介されているサイトがいくつかありました1ので、ここでは概要のみの記載とし、詳細は割愛させていただきます。

仮想サーバ(1):Drill

MapR社がDrillインストール済みの仮想アプライアンスを提供していますので、こちらを利用します。
https://mapr.com/products/mapr-sandbox-hadoop/download-sandbox-drill/

ファイル名:MapR-Sandbox-For-Apache-Drill-1.10.0-5.2.2.ova
をダウンロードして、VirtualBoxへ「仮想アプライアンスのインポート」を行います。

仮想サーバ(2):MariaDB

VirtualBoxより仮想マシンを新規作成し、CentOS7の媒体をマウントしてインストールします。
OS起動後はyumでMariaDBをインストールします。
バージョンは5.5.56を利用します。

テストデータ

CSVファイル

CSVファイルを2つ用意しました。

  • CSVファイルその1:「neko.csv」

    • id:1以上のユニークな数値
    • name(名前):ランダムな文字列
    • age(年齢):1~100までのランダムな数値
    • personality_code(性格コード):1~10のランダムな数値

    データのイメージは以下の通りです。

id name age personality_code
1 e7b261369b 28 3
2 6f12edf39a 21 5
3 83f5eb38dc 42 8
4 792bba127b 34 9
5 46f48bd851 80 2
6 75e3dbb099 15 4
7 715e2cbfb0 44 1
8 748522d354 86 3
9 b745f04675 9 10
10 50c5abb95e 32 3

  上記のようなデータを20,480,000レコード用意しました。

  • CSVファイルその2:「personality.csv」 ※JOIN用のデータです
    • code(性格コード):1~10
    • personality(性格):コード値の説明

  データのイメージは以下の通りです。

code personality
1 friendly
2 curious
3 gracious
4 easygoing
5 brave
6 ambitious
7 funny
8 odd
9 shy
10 violent

  こちらは上記の10レコードのみです。

CSVファイルを作成したら、仮想サーバ(1) のHDFSにPUTしておきます。

> hadoop fs -put neko.csv personality.csv /data

> hadoop fs -ls /data
Found 8 items
-rw-r--r--   1 mapr mapr    1034773 2017-08-03 16:46 /data/customers.all.csv
drwxr-xr-x   - mapr mapr          1 2017-08-03 16:46 /data/flat
-rwxr-xr-x   1 mapr mapr  502719458 2017-12-13 04:51 /data/neko.csv
drwxr-xr-x   - mapr mapr          1 2017-08-03 16:46 /data/nested
drwxr-xr-x   - mapr mapr         10 2017-08-03 16:46 /data/orders
-rwxr-xr-x   1 mapr mapr        112 2017-12-13 04:51 /data/personality.csv
drwxr-xr-x   - mapr mapr          1 2017-08-03 16:46 /data/products
drwxr-xr-x   - mapr mapr          0 2017-08-03 16:46 /data/views

MariaDBスキーマ

上記のCSVファイルに倣って、仮想サーバ(2) のMariaDBにテーブルを作成します。
テーブル定義は以下の通りで、特にインデックスは張っていません。

neko
+------------------+--------------+------+-----+---------+----------------+
| Field            | Type         | Null | Key | Default | Extra          |
+------------------+--------------+------+-----+---------+----------------+
| id               | int(11)      | NO   | PRI | NULL    | auto_increment |
| name             | varchar(255) | YES  |     | NULL    |                |
| age              | int(11)      | YES  |     | NULL    |                |
| personality_code | int(11)      | YES  |     | NULL    |                |
+------------------+--------------+------+-----+---------+----------------+
personality
+-------------+--------------+------+-----+---------+-------+
| Field       | Type         | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| code        | int(11)      | NO   | PRI | NULL    |       |
| personality | varchar(255) | YES  |     | NULL    |       |
+-------------+--------------+------+-----+---------+-------+

テーブル作成が完了したら、CSVファイルからデータをINSERTしておきます。

クエリ

今回は、以下の5パターンのSELECTクエリを実行してみました。

  1. COUNT
  2. LIKE
  3. JOIN
  4. GROUP BY
  5. ORDER BY

具体的なSQL文は以下の通りです。

COUNT

  • Drillの場合
    テーブル名に相当する部分は、HDFS上のファイルパスをバッククォートで囲った形式で記述します。
SELECT COUNT(*) FROM `/data/neko.csv`;
  • MariaDBの場合
SELECT COUNT(*) FROM neko;

LIKE

  • Drillの場合
SELECT * FROM `/data/neko.csv` WHERE `/data/neko.csv`.name LIKE '%abcd%';
  • MariaDBの場合
SELECT * FROM neko WHERE name LIKE '%abcd%';

JOIN

  • Drillの場合
SELECT * 
FROM `/data/neko.csv` 
LEFT JOIN `/data/personality.csv` 
  ON `/data/neko.csv`.personality_code=`/data/personality.csv`.code 
WHERE `/data/neko.csv`.age=35;

 毎度ファイルパスを記述するのが面倒な場合は、別名記法もいけます

SELECT * 
FROM `/data/neko.csv` AS neko 
LEFT JOIN `/data/personality.csv` AS per 
  ON neko.personality_code=per.code
WHERE neko.age=35;
  • MariaDBの場合
SELECT * 
FROM neko 
LEFT JOIN personality 
  ON neko.personality_code=personality.code 
WHERE age=35;

GROUP BY

  • Drillの場合
SELECT COUNT(*) 
FROM `/data/neko.csv` 
WHERE `/data/neko.csv`.age=50 
GROUP BY `/data/neko.csv`.personality_code;
  • MariaDBの場合
SELECT COUNT(*) 
FROM neko 
WHERE age=50 
GROUP BY personality_code;

ORDER BY

  • Drillの場合
    データはテキスト型として扱われるため、数値型にキャストしてあげないと正しくソートがされないので要注意です。
SELECT * 
FROM `/data/neko.csv` 
WHERE age=20 
ORDER BY CAST(`/data/neko.csv`.personality_code AS INT);
  • MariaDBの場合
SELECT * 
FROM neko 
WHERE age=20 
ORDER BY personality_code;

性能測定

測定条件

  • 特に負荷のかかっていない状態で単発のクエリを発行します。
  • SQLコンソール(Drillであればsqlline、MariaDBであればmysql)上でクエリを実行し、結果表示されるレスポンスタイムを測定数値として採用します。
  • WHERE句の条件を微妙に変えつつ、5回実行した結果の平均値を採用しています。
    • 今回の計測では飛び抜けた値(外れ値)は見られませんでした。

測定結果

数値の単位はsecです。

クエリ  Drill   MariaDB
COUNT 3.97 3.19
LIKE 6.77 7.83
JOIN 14.17 5.62
GROUP BY 4.59 4.74
ORDER BY 17.26 6.81

JOINやORDER BYが苦手なようですが、全般的にMariaDBと比較して劇的に遅いという訳でもなさそうです。
無論、MariaDBはインデックスを張っていないので、さらに高速化できる余地は残しています。
とは言え、HDFSに置いただけのテキストファイルにいきなりSQLを投げて、チューニングしていないRDBとほぼ遜色ない性能が出る、となると魅力的に感じます。

所感

あらかじめデータ構造や発行するクエリが決まっているようなシーンであれば、やはりRDBの方に分があります。
Drillの使いどころとしては、日々増大していく非構造化データに対してアドホックにクエリを投げたい(多少は時間がかかってもいい)、というケースで力を発揮できるだろうと思いました。


  1. 以下の記事を大変参考にさせていただきました。
    Apache Drill を使ってみよう!!
    http://azure.sios.jp/archives/jtp-apachedrill-20170308