こんにちは!Yokoです。
皆さんはQlikの表示レスポンスについて、どこまで許容していますか?
僕は概ね10秒以内に返ってくればOKで、それを超えるとユーザとしては「おっせーなー!」と感じると思っています。
なので、10秒を超えてしまう時は、何らかの対策を施しますが、どうにもならない場合はお客様にお伝えするようにしています。
で、「何らかの対策」というのが経験がモノを言うところで、データモデルや数式を修正したり、表示条件を入れたりするのですが、ちゃんと実測する機会もないので、この機会にベンチマークしてみようと思うに至りました。
今回取り上げたいのは、データ量が増えることでどのようにレスポンスに影響を与えるか…です。
では早速、実験していきましょう。
比較するモデル
そもそも、この記事を書こうと思ったきっかけは、前回投稿した「From Toデータの扱い」で、レコード数の割にパフォーマンスが出ているなと感じたことでした。
「From Toデータの扱い」は2回シリーズになっていて、2つの異なるアプローチで解決したわけですが、この2つのアプローチのパフォーマンス比較をしていきたいと思います。
これらの共通の目的は、「From To」のデータから月ごとの契約者数の推移を12ヵ月分表示するということです。
それに対して、以下のような2つのモデルを作成してきました。
| モデル名称 | テーブル構成 | 説明 |
|---|---|---|
| Pickモデル | customer + calendar | customerテーブルからPick(Match…)の数式で12ヵ月表示 ※データ少ない |
| データ自動生成モデル | customer + contract + calendar | customerテーブルからcontractデータを生成し、contractテーブルからシンプルな数式で計算 ※contractテーブルはデータ量多い |

以上のモデルで、customerの件数を500万人、1000万人、1500万人、2000万人、2500万人、3000万人とロードスクリプトで増やしてみます。
Pickモデルでは、最大でも3000万件のレコードになりますね。
データ自動生成モデルでは、会員数を増やしていくと、会員数の30〜40倍のレコードがcontractテーブルに格納されることになりますので、データ量の増大がレスポンスにどう影響するのでしょうか?
それぞれの言い分はこんな感じになるのではないかと思います。
■Pickモデル(データ量的には問題ないが、数式がどれくらい重いか…)
- 最大でも3000万件だから、Qlikでは楽勝な件数ではある
- しかし、SET分析を使って集計するというやや複雑な数式
- Pick(Match…を使って12ヶ月分を表示するということは、12個の分岐式になる?
■データ生成モデル(数式はシンプルだけど、恐ろしいほどのデータ量になる…)
- Count(Distinct 会員番号)という、ものすごーくシンプルな数式
- 3000万人の契約月数のデータって、10億件を超えるレコード数になるのでは?
- しかも、アプリサイズが大きくなった場合、Qlik Cloudのメモリでスワップとか発生しない?
さて、どっちが速いのでしょうか?
レコード数とデータサイズ
ランダムにデータを作成するロードスクリプトで、会員数を徐々に増やしていき、レコード数とデータサイズ(ここではアプリサイズ)を見ていきます。
まずレコード数ですが、会員数を500万人刻みで3000万人まで増加させていった場合のデータ生成モデルにおけるcontractテーブルのレコード数は以下のとおりです。

500万人の時で既に2億レコード近くになっています。3000万人の時で11億レコードを超えてしまっている😱
11億レコードって、インメモリなら、そもそも限界ギリギリの件数なんじゃないの?
次にデータサイズを見てみましょう。

Pickモデルでのアプリサイズは3000万人分でも175MBです。小さい〜!
一方、contractデータを生成させると、500万人分で既に804MBで、3000万人分だとなんと5GB!
いやー、これは限界っすね。
評価環境のアプリサイズの上限が5GBですから、ホントにギリギリでした!(偶然です)
2つのモデルのレスポンスを計測
いよいよ、結果発表です!
ジャーーーン!!

データ生成させたほうが圧倒的に速いという結果になりました。
(お断りしておきますが、iPhoneのストップウォッチで計測しているので、計測結果は僕の反射神経にも依存しております🙇♂️)
レコード数=11.5億件から集計しても8.4秒!
アプリサイズが5GBになっているというのに!
甘く見てました😅
Qlik速いんですね!
それに対して、Pick(Match…で12分岐した場合は、500万件でも16.8秒もかかっている。
Pickとはいえ、やっぱり分岐は分岐なんだなあ…
If文を12個書いているようなもんだから、そんなものかもしれないんだけど、予想以上に遅かったです。
Pickモデル〜数式の中での分岐の数だけ遅くなる
予想以上に遅かったPickモデルですが、Pickモデルでのデータ件数に対するアプリサイズとレスポンスは以下のようになります。

これからわかるのは、レコード数に応じてアプリサイズもレスポンスも見事に比例して大きくなるということです。
500万レコードで16.8秒というのは運用には、この時点で耐えられないですね。
比例して増えるということを考えると、このモデルで運用に耐えうるレコード数は200万レコードというところですかね。
補足しますと、Pick(Matchでの条件分岐の数でもレスポンスはかなり変わります。
1000万レコードで34.5秒かかるというのは12分岐の時であって、分岐なしでは5.3秒、2分岐で7.0秒、3分岐で9.8秒といった感じでした。
ということは、1000万レコードあるとすれば、メジャーでSET数式の分岐って、逆算すると、せいぜい3つくらいに留めないとユーザはストレスを感じるくらいに遅くなるということですね。
こんなふうにPickを使った場合、条件分岐の数で、かなりレスポンスが変わることが改めてわかりました。
Pickは条件の記述がしやすく、わかりやすいので、たくさん条件分岐を書きたくなりますが、分岐が増えれば増えるほど重くなっていくので、ほどほどにしておかないといけないですね。
データ生成モデル〜アプリが肥大化したとしても、データ量に比例して遅くなるだけ
データ生成モデルのデータ件数に対するアプリサイズとレスポンスはこちらです。

データサイズとレスポンスの傾きに注目して下さい。
データサイズはレコード数に応じて、きれいに比例して増加していますが、レスポンスの傾きのほうが低くみえます。
0〜1.86億レコードの間の実測を行えば正確に算出できるのかもしれませんが、レコード数の増加に比して、やや直線的ではないようにも見えますが、いずれにせよ、レコード数の増加に伴い、ほぼリニアにレスポンスが遅くなると言っていいでしょう。
だから、データを蓄積していくと年々しだいに遅くなってきているはずなのに、僕らはそれに気づかず使っているだけなんでしょうね。
そして、評価環境ギリギリの5GBというアプリサイズでも十分にレスポンスが出ていることを考えると、Qlik Cloud上でメモリのスワップは発生していないと考えていいですね。
通常はアプリを起動した時に、メモリ上に展開された時点で、元の数倍のサイズのメモリを占有しますから、比較的余裕のあるインフラであると推測されます。
おそらく、16GBとか32GBのメモリが載っている環境で動いているのに相当するのではないかと思います。
オンプレで構築した場合、サーバ上で起動中の全アプリ分のメモリが必要ですが、Qlik Cloud上では、同時に起動中のアプリ全体に対するメモリサイズの制限はありませんので、Qlik Cloudのほうが運用負荷も少なくてラクですね。
まとめ
正直、予想していたことではあるのですが、ここまで顕著な結果になるとは思いませんでした😄
特に、データ量に応じて、レスポンスはリニアに増加していくだけだし、数式内での条件分岐は分岐の数だけ遅くなる…
そう考えると、これまで作ってきたアプリも直したいところがちらほら😅
で、まとめるとこういうことになるかと
レコード数を増やさずに数式で解決するより、思い切ってレコード数を増やしたほうがいい!
- PickやIfの分岐が多くなればなるほど顕著にパフォーマンスが劣化する
- シンプルな数式であれば、レコード数が増えても予想以上に性能が出ている
- Qlik Cloudの環境であれば、アプリサイズ上限まで使い切るくらいでも良いのかも
(但し、データ量課金の方は注意して下さいね)
もちろん、データモデルが複雑になれば、結果は異なるとは思います。
例えば軸で指定した項目が属するテーブルから、メジャーで指定した項目が属するテーブルまでの結合の回数なんかも影響しますよね。
が、シンプルなデータモデルで評価すればこういう結果ですので、
- データ量に応じたデータモデル設計
- データ量が増えた時のパフォーマンス予測
- 現在のQlikアプリのパフォーマンス改善(特にIf文やMatch)
などには有用な実験だったのではないでしょうか。
以上、是非参考にしてみて下さい。
ではまた!
関連記事はこちら
Qlikの日付処理のベストプラクティス〜第8回 From Toデータの扱い その1〜
Qlikの日付処理のベストプラクティス〜第9回 From Toデータの扱い その2〜


