Redash遅い・重いとは言わせない! 高速ダッシュボードで快適なデータ分析ライフを送るためのTips

## はじめに
言わずと知れたダッシュボードツールのRedash。複数のデータソースに対して、クエリを発行する事で自由な切り口でデータを可視化する事ができます。また、フィルタ機能を使った絞り込みにも対応しているため、定点的な観測以外にもクロス集計程度なら、これ1つでこなせてしまう優れものです。

私個人のキャリアでは、ダッシュボードツールとして、DOMO/Tableau/GoogleDataStudio(GAメインなこれもオススメです)など使ってきましたが、Redashが1番取っつきやすく、SQLが分かれば手軽に利用できて好みです。

## 意外と根が深い?Redash重い問題
ネット上で記事を見ていると、"データソースに対して、クエリを発行する"図式をよく見ますが、重たいクエリを投げると、Redashが落ちる、もしく、動作が重くなる事がよく起こります。

特に、チーム・事業部全体で環境を共有している場合、四方八方からクエリが飛んでくるので、捌き切れなくなるケースも多く、管理者に対して"すみません。。重いクエリを投げてしまいまして、再起動お願いできますか?"的なちょっと気まずいやり取りが頻繁に発生-->ストレスフルになりRedashを触らなくなる。という、負のループに陥ることも。

ダッシュボードツールは、エンジニアのみが使うものではなく、PMはもちろん、営業・企画・バックオフィスはたまた、経営陣など、チーム全員が自由にストレスなく使えて初めて意思決定に活用でき効果を発揮するものだと思います。Excelやスプレッドシートなど他のツールを行き来する事なく、なるべくRedash内で踏み込んだ分析までできると、より便利なものになります。今回はドリルダウン分析を容易にするための、クエリフィルタ機能の活用についても紹介します。

少し一手間を加えるだけで、スタティックで動作が遅いダッシュボードが、爆速で動作するドリルダウン可能なダッシュボードに変わるので、同じ様な悩みを抱えている方いましたら、参考にしてみて下さい。

## 3行まとめ
### Redashの発行クエリはなるべく軽くしよう!
### クエリフィルタ機能を活用して、深掘りを可能にしよう!
### 素敵なデータ分析ライフを始めよう!

## 対象読者
- Redash(やその他のクエリ発行タイプのBIツール)を利用していて、動作速度を改善する方法を探している方
- 一歩進んだRedashの活用方法を知りたい方

## 本記事の動作環境
- Redash ver 4.0.1

## 前提
- 本記事では、データソースとしてGoogleBigQuery上のテーブル利用を一例に説明しています。一部BigQueryに特化した内容が含まれてきますが、その他のデータソースをお使いの場合も、適宜内容を読み替えて頂ければと思います。

## サンプルデータ
本記事では、GoogleBigQueryからアクセス可能なパブリックなアクセスログデータ、firebase-analytics-sample-dataを利用します。架空のゲームアプリのアクセスログを想定したデータセットになります。データの中身は本題とは関係ないので、あまり気にしないで下さい。

参考リンク:https://cloudplatform-jp.googleblog.com/2016/09/bigquery-firebase-analytics.html

## 分析爆速化Tips①:Redashから発行するクエリは、SELCET/FROMのみのシンプルなものに制限する

Redashの動作が重くなる原因は、ひとえに【計算コストの高いクエリを発行するから】これに尽きます。つまり、発行するクエリをよりシンプルにする事が動作高速化の鍵になります。(当たり前と言えば、当たり前ですが)

一手間をかけて、Redashからのクエリははあくまで集計済みテーブルをSELECTするだけにして、テーブル集計は外出しで行うようにします。

自分のケースでは、元々コストの高いクエリを多用する、30個程のグラフが配置されたダッシュボードがあり、重過ぎて使いものにならない状態だったのですが、クエリをミニマムなものにする事で、10秒程度でサクッと更新される様になりました。BigQueryの場合のTipsを以下に記入しますが、どの様なデータソースであっても近い方法で対処できるかと思います。

### GoogleBigQueryと連携する場合
WEB系の企業でしたら、事業データや、アクセスログを取り敢えずBigQueryに溜め込んでいる環境を構築している場合も多そうです。その場合は、RedashでJOINなどを含むクエリは一切発行せずに、事前にバッチ集計を行う事で対処します。

<img width="755" alt="スクリーンショット 2018-08-19 12.39.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/56466/42e7e6bb-9ede-34ab-3c69-05463681ff79.png">

#### (1)発行用クエリを作成する
例えば、①DAU②国別のアクセスログ③日別の課金額を集計するケースを想定すると、それぞれの以下の様なクエリを発行することになります。

```sql:発行する集計クエリ
-- ①DAUを集計するクエリ
SELECT
event_dim.date
,count(distinct user_dim.app_info.app_instance_id) as user_count
FROM
  `firebase-analytics-sample-data.ios_dataset.app_events_2016*`
  ,unnest(event_dim) as event_dim
Group by event_dim.date
Order by date

-- ②日別の課金額を集計するクエリ
select date
,sum(int_value) as spent_virtual_money
from
(SELECT date
,event_param.value.int_value
FROM
  `firebase-analytics-sample-data.ios_dataset.app_events_2016*`
   ,unnest(event_dim) as event_dim   
   ,unnest(event_dim.params) as event_param   
WHERE event_dim.name = "spend_virtual_currency"
) as s
group by date
order by date

-- ③各国別のユーザー内訳を集計するクエリ
SELECT user_dim.geo_info.country
,count(distinct user_dim.app_info.app_instance_id) as user_count
FROM
  `firebase-analytics-sample-data.ios_dataset.app_events_2016*`
   ,unnest(event_dim) as event_dim   
GROUP BY user_dim.geo_info.country

```
#### (2)Redashから直接実行せず、コマンドラインで中間テーブルを生成する
これらを直接Redashからクエリ発行すると動作遅延に繋がるため、中間テーブルをBigQuery上に作成し、RedashからはSelectを行うのみにします。

BigQueryでクエリ発行とテーブル保存を行う際には、[bqコマンドラインツール](https://cloud.google.com/bigquery/bq-command-line-tool?hl=ja)が非常に便利です。1文で、クエリの発行+任意の名称でテーブルを上書きする事ができます。集計したいクエリの数だけ、コマンドを増やしていけばスケールアップにも対応できます。

```bash:bqコマンド記入例
bq query --use_legacy_sql=false --destination_table="保存先のテーブルの名称"  --replace  --flagfile "発行したいクエリのパス"
```
| オプション       |       説明 |  
|:-----------------|:------------------|
| --user_legacy_sql             |falseにすると、stanadardSQLを使用します|
| --destination_table           |クエリの実行結果の保存先テーブルを指定します|
| --replace             |テーブルの上書きを許可するかを設定します。定期実行する場合は、Trueにする事が多いでしょう|
| --flagfile               |bq queryで実行する、クエリファイルのパスを記入します。.sqlでクエリを記入したいファイルを指定します。 |

今回は、BigQuery上に"daily_kpi"という名称でデータセットを作成し、中にテーブルを生成します。

```bash:bqコマンドを実行例
bq query --use_legacy_sql=false --destination_table="daily_kpi.01_dau"  --replace  --flagfile "01_dau.sql"
```
上手く行けば、コマンドライン上で以下の様に結果が表示され、、、
<img width="644" alt="スクリーンショット 2018-08-19 13.00.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/56466/11b6028d-a69c-39f2-857c-51396c51fdeb.png">
BigQuery上でテーブルが生成されている事も確認できます。
<img width="705" alt="スクリーンショット 2018-08-19 13.02.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/56466/37d72e50-1310-58ea-01bd-2119f0f604e4.png">

#### (3)Redashからクエリを発行する
ここまでお膳立てができれば、集計済みテーブルに対してRedashからクエリを発行します。日別の集計結果でしたら、たかだか数１００件のレコードでしょうし、その他のケースでも可視化用のテーブルと割り切って、なるべくレコード数を少なく保持しておく事が重要です。(数万件くらいなら、十分高速に動作しますけど。)

<img width="617" alt="スクリーンショット 2018-08-19 13.10.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/56466/7a188f66-6547-5a98-d11d-65cd059097ba.png">

全てのクエリで対応するのは難しくても、特定のクエリで重いものがあれば外出しして計算する事で、グッと動作を軽くする事ができます。

## 分析爆速化Tips②:クエリフィルターで、ダッシュボードにドリルダウン機能を持たせる
Tips①で、表示速度が上がった後はクエリフィルタ機能を用いる事で、わざわざ新規クエリ発行や、別ツールの併用を行わなくても、RedashUI上で分析者が深掘りできる様にします。

#### (1)各々のクエリにフィルタを設定する
<img width="608" alt="スクリーンショット 2018-08-19 13.23.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/56466/6ece465a-5f1b-34ab-081e-5d4ee967bb2e.png">
概念的には、上記の図の様になるのですが、クエリ毎にフィルタを設定する事で絞り込み機能を追加する事ができます。具体的には、Where句の中で使用する事が多くなると思います。
![Untitled(3).png](https://qiita-image-store.s3.amazonaws.com/0/56466/378c46b1-0dd5-d663-be2f-3403f41d6d10.png)

また、個別のフィルタを同一の名称で設定しておくとダッシュボード化した際に、横断的な絞り込み機能が使えるのですが、こちらが非常に強力です。

#### (2)後はダッシュボード上でゴリゴリドリルダウン分析が実行できます
↓今回の例ですと以下の様に動作します。(ダッシュボード全体に日付範囲を設定する)
![マイムービー (1).gif](https://qiita-image-store.s3.amazonaws.com/0/56466/9c302109-3f71-c732-9e99-16bd787cbf83.gif)

今回は、日付の絞り込みのケースを紹介しましたが、例えば以下の様な利用用途も想定されるでしょう。

- Eコマース:店舗名で絞り込み可能にして、店舗の詳細閲覧用のダッシュボードを作成する
- ソーシャルゲーム:ユーザーIDで絞り込み可能にして、個別ユーザーの行動を深掘りする...

## Redashで快適な分析ライフを!
上記Tips2つを活用すれば、高速で動作して、深掘り分析も可能なダッシュボードが完成するはず!イライラを取り除く事で、グッと組織内でのデータ活用が進むと思います。拙い事例ではありますが、お役に立てれば幸いです。