はじめに
先日ふと気になり、QlikViewのデータ構造が列指向なのか調べてみました。
その際に見つけた記事について、自分なりにまとめてみました。
出典:Symbol Tables and Bit-Stuffed Pointers - Qlik Community - 1475369
結論からいうと、QlikViewは厳密には列指向ではなく独自のデータ構造となっているようです。
ただ内容としては、列ごとで圧縮する構造など、列指向とほぼ同じという印象でした。
そもそも行指向・列指向とは
行指向・列指向とは、データを格納・取得・管理するための構造のことです。
一般的にECサイトなどの業務システムで使用されるデータベースでは、行指向(行ストア)の構造が使われます。
一方、データ分析のためのデータマートやDWHでは、列指向(列ストア・カラムナー)の構造が使われます。
それぞれの特徴は次のとおりです。
-
行指向
- ECサイトなどの業務システム向けの仕組み
- 行ごとにデータが格納される
- 取得したいカラム以外のすべてのカラムも読み込まれてしまう
- 行を素早く特定できる
-
列指向
- DWHなどの分析システム向けの仕組み
- 列ごとにデータが格納される
- 必要なカラムのみ読み込むことができる
- 行単位の処理は不向き
列指向は列ごとに圧縮するため、同一のデータが多いほどデータ圧縮の効果は高くなります。
QlikViewのデータ構造について
ここから本題です。
まずQlikViewは、ロードしたデータを2つのテーブルタイプに変換します。
データテーブルとシンボルテーブルです。
シンボルテーブルは、ロードしたテーブルのカラムの数だけ作成されます。
たとえば3つのカラムからなるテーブルをロードした場合、Qlikのエンジンは1つのデータテーブルと3つのシンボルテーブルへ変換します。
データテーブル(Data table)
データテーブルは、ロードしたテーブルと同じ数の行、同じ数の列で構成されます。
テーブルにはポインターのみを保持しており、データそのものは含まれていません。
しかし、ポインターを使ってシンボルテーブルから値を検索するため、情報が失われることはありません。
シンボルテーブル(Symbol tables)
シンボルテーブルは、ポインターとデータの値(テキストや数値)の2つのカラムを保持しています。
データの値は一意になっており重複はありません。
シンボルテーブルは、データテーブルから値を検索するためのテーブルです。
ビットスタッフドポインター(bit-stuffed pointers)
データテーブルとシンボルテーブルをつなぐポインターをビットスタッフドポインター(bit-stuffed pointers)といいます。
このポインターは、データ値を表現するのに必要最低限なビット数だけで構成されています。
たとえばある列に4種類の値があった場合、4つの値を表現するのに必要なビット数は次の表のように2ビットであるため、データテーブルが非常に小さくなります。
Pointer | 性別 |
---|---|
00 | 男 |
01 | 女 |
10 | その他 |
11 | 未回答 |
最適化の例
シンボルテーブルとビットスタッフドポインターという構造によって、Qlikはデータを圧縮できます。
Qlik Senseについても同じエンジンを使っているため、QlikViewとQlik Senseのどちらも同様です。
この構造には、次のような特徴があります。
- ポインターの長さは、シンボルテーブルのサイズに影響する
- 列内の一意な値の数は、ポインターの長さだけではなく、シンボルテーブルの行数にも影響する
Qlikを最適化するための例を紹介します。
Autonumber()を使用する
たとえば、表示する必要のない長い連結された複合キーがあった際には、Autonumber()を使用するとデータを最適化できます。
ポインター自体が連番の情報をもつため、シンボルは不要になりシンボールテーブルのサイズをゼロにできます。
列を複数に分解する
秒単位でデータを保持しているタイムスタンプの列があった際に、時間を15秒間隔や1分単位で丸めると、一意の件数を減らすことができるため、データサイズを縮小できます。
また、日と時間の2つの列に分割しても一意の件数を減らすことができます。
一意の値が10万種類を超えるようなら、2つの列に分割することを検討する必要があります。
さいごに
今回参考にした記事が載っている「QlikView Design blog」には、他にもQlikに関する情報がたくさんありそうでした。
今回Qlikの内部構造について調べてみましたが、日本語の記事はほとんど見つけらなかったので、頑張って英語の記事を読んでみようと思いました。