Kylin Cube構築プロセスの最適化


原文住所:https://kylin.apache.org/docs16/howto/howto_optimize_build.html
Kylinは、1つのcubeのbuildプロセスをいくつかのサブステップに分解し、これらのサブステップをシリアルで実行する.これらの手順には、Hive操作、MRタスク、その他のタイプの作業が含まれます.毎日多くのcubeがbuild操作を行うと、このプロセスを加速させることができます.ここではいくつかのアドバイスが参考になりますが、buildの順に紹介します.

Create Intermediate Flat Hive Table


このステップでは、ソースHiveテーブルからデータ(すべての関連テーブルjoinの後のデータ)を抽出し、一時的なフラットテーブルに挿入します.cubeがパーティション列を持つ場合、Kylinは時間条件を追加し、条件に合致するデータのみがキャプチャされることを保証します.この手順に関連するHiveコマンドをログに表示できます.次のようになります.
hive -e "USE default;
DROP TABLE IF EXISTS kylin_intermediate_airline_cube_v3610f668a3cdb437e8373c034430f6c34;

CREATE EXTERNAL TABLE IF NOT EXISTS kylin_intermediate_airline_cube_v3610f668a3cdb437e8373c034430f6c34
(AIRLINE_FLIGHTDATE date,AIRLINE_YEAR int,AIRLINE_QUARTER int,...,AIRLINE_ARRDELAYMINUTES int)
STORED AS SEQUENCEFILE
LOCATION 'hdfs:///kylin/kylin200instance/kylin-0a8d71e8-df77-495f-b501-03c06f785b6c/kylin_intermediate_airline_cube_v3610f668a3cdb437e8373c034430f6c34';

SET dfs.replication=2;
SET hive.exec.compress.output=true;
SET hive.auto.convert.join.noconditionaltask=true;
SET hive.auto.convert.join.noconditionaltask.size=100000000;
SET mapreduce.job.split.metainfo.maxsize=-1;

INSERT OVERWRITE TABLE kylin_intermediate_airline_cube_v3610f668a3cdb437e8373c034430f6c34 SELECT
AIRLINE.FLIGHTDATE
,AIRLINE.YEAR
,AIRLINE.QUARTER
,...
,AIRLINE.ARRDELAYMINUTES
FROM AIRLINE.AIRLINE as AIRLINE
WHERE (AIRLINE.FLIGHTDATE >= '1987-10-01' AND AIRLINE.FLIGHTDATE < '2017-01-01');
"

Hiveコマンドを実行すると、Kylinはconf/kylin_を使用します.hive_conf.xmlのコンフィギュレーション・アイテム.たとえば、より少ないコピー数とHiveを許可するmapper接続操作を使用します.必要であれば、他の構成項目を追加することもできます.
Cubeのパーティション列(ここでは「FLIGHTDATE」)がHiveテーブルのパーティション列と同じ列である場合、その列をフィルタリングすると、Hiveは条件に合わないパーティションを非常に迅速に除去します.したがって、Hiveのパーティション列(パーティション列が日付の場合)をCubeのパーティション列として使用することを強くお勧めします.これは、データが非常に多いテーブルではほとんど必要です.そうしないと、Hiveはこのステップを実行するたびにすべてのファイルをスキャンする必要があり、時間がかかります.
Hiveがファイルのマージを許可している場合は、「conf/kylin_hive_conf.xml」でコンフィギュレーション・アイテムを使用してこの機能を無効にすることができます.Kylinには独自のファイルマージ方法があるため(以下で説明します):
<property>
    <name>hive.merge.mapfilesname>
    <value>falsevalue>
    <description>Disable Hive's auto mergedescription>
property>

Redistribute intermediate table


前の手順の後、HiveはHDFSのディレクトリにデータファイルを生成しますが、ファイルによっては大きくなる可能性があります.また、ファイルによっては小さく、空になる可能性があります.ファイルサイズ分布の不均衡は、後続のMRタスクの不均衡をもたらします.一部のmapperタスクはすぐに実行され、他のmapperは遅く実行される可能性があります.これらのデータ分布をより均一にするために、Kylinは、各データファイル内のデータを再割り当てするためのステップを追加した.次は簡単な出力です.
total input rows = 159869711
expected input rows per mapper = 1000000
num reducers for RedistributeFlatHiveTableStep = 160

データの再割り当て後に実行されるHiveコマンドは次のとおりです.
hive -e "USE default;
SET dfs.replication=2;
SET hive.exec.compress.output=true;
SET hive.auto.convert.join.noconditionaltask=true;
SET hive.auto.convert.join.noconditionaltask.size=100000000;
SET mapreduce.job.split.metainfo.maxsize=-1;
set mapreduce.job.reduces=160;
set hive.merge.mapredfiles=false;

INSERT OVERWRITE TABLE kylin_intermediate_airline_cube_v3610f668a3cdb437e8373c034430f6c34 SELECT * FROM kylin_intermediate_airline_cube_v3610f668a3cdb437e8373c034430f6c34 DISTRIBUTE BY RAND();
"

まず、Kylinはテンポラリ・テーブルのロー数を取得します.そして、この行数に基づいて、データの再割り当てが必要なファイルの数を取得することができる.Kylinのデフォルトのファイルには、1百万行のデータが含まれています.この例では、合計1.6億行のデータと160個のreducerがあり、各reducerにファイルが書かれています.後続のMRステップでは、Hadoopは、これらのファイルを処理するために同じ数のmapperを起動する(通常、1つのHDFSブロックよりも1百万行のデータのサイズが小さい).日常的なデータ規模が大きくない場合やHadoopクラスタに十分なリソースがある場合は、「conf/kylin.properties」で構成項目「kylin.job.mapreduce.mapper.input.rows」をより小さな値に設定することで、次のようにしてより高い同時性を得ることができます.
kylin.job.mapreduce.mapper.input.rows=500000

次に、Kylinは、HiveQL「INSERT OVErWIRTE TABLE…DISTRIBUTE BY…」を実行することによって、指定された数のreducerにデータ行を再割り当てする.
ほとんどの場合、Kylinは、これらのreducerのデータ行をHiveにランダムに再割り当てして、これらのファイルがサイズに近いことを保証するように要求します.このとき,再割当て文は「DISTRIBUTE BY RAND()」である.
Cubeで「shardby」次元列が決定された場合(Cubeの「Advanced setting」インタフェースで設定されている)、この次元列が基数の大きい次元列(例えば「USER_ID」)である場合、Kylinは、Hiveに次元列の値を使用してデータを再割り当てするように要求します.カラムに同じ値を持つデータ行は、同じファイルに割り当てられます.これは、データが再割り当てされるだけでなく、追加のコストを消費することなくデータが再分類されるため、ランダム割り当てよりも優れています.これは、後続のCube構築プロセスに役立ちます.特定の場合、この最適化は、構築時間を40%削減することができる.この場合の再割当文は「DISTRIBUTE BY USER_ID」である.
注意:1.「shard by」に設定された次元列は、基数の大きい次元列であり、多くのcuboidに表示されます(少ないcuboidにのみ表示されるわけではありません).再割り当てに使用すると、各時間間隔で等分布が得られる場合があります.逆にデータが傾き、構築速度が低下します.典型的な適合シナリオは、「USER_ID」、「SELLER_ID」、「PRODUCT」、「CELL_NUMBER」などであり、一般的な基数は1000より大きくなければならない(reducerの数よりはるかに大きい).2.「shard by」の使用は、Cubeストレージにおいて他の利点があるが、本明細書の議論の範囲内ではない.

Extract Fact Table Distinct Columns


このステップでは、Kylinは、MRタスクを実行することによって、ディクショナリ符号化のために次元列のdistinct値を取得する.
実際には、HyperLogLogカウンタを使用して各cuboidの行数を推定し、cubeの統計情報を順次収集するなど、他の作業も行われています.mapperタスクの実行が非常に遅いことを発見した場合、cube設計が複雑であることを意味することによって、参考にすることができます:Cube設計の最適化、cubeを最適化し、cubeをより簡素化します.reducerでOOMエラーが発生した場合、通常、cuboidの次元の組合せ数が多すぎるか、デフォルトのyarnメモリ割り当てが需要を満たすことができないことを意味します.この手順が合理的な時間内に完了しない場合は、実際のbuildプロセスに時間がかかるため、cubeを再設計してください.
サンプリングスケールを減らすことができます(kylin.propertiesでkylin.job.cubing.inmem.sampling.percent構成項目を設定することによって)このステップの実行を加速させることができますが、これはあまり効果的ではなく、cube統計の正確性にも影響する可能性がありますので、一般的には推奨されません.

Build Dimension Dictionary


前のステップですべての次元列のdistinct値が取得され、Kylinはメモリに辞書を構築します(次のバージョンではMRタスクに移動します).通常、このステップは速いですが、distinct値のセットが大きい場合、Kylinは「Too high cardinality is not suitable for dictionary」などのエラーを報告する可能性があります.UHC(大容量)列の場合は、「fixed_length」、「integer」など、他の符号化方法を使用します.

Save Cuboid Statistics and Create HTable


この2つのステップは軽量級で、速いです.

Build Base Cuboid


このステップは,層毎アルゴリズムの第1ラウンドのMRタスクである一時テーブルにより基本的なcuboidを構築する.Mapperの数はステップ2のreducerの数に等しい.一方、Reducer(ここでは、このステップで開始されたreducerを指す)の数は、cubeの統計によって推定されます.デフォルトでは、500 Mごとに1つのreducerが使用されます.reducerの数が少ないことに気づいたらkylinでpropertiesでは、構成項目「kylin.job.mapreduce.default.reduce.input.mb」のより小さな値を設定して、kylin.job.mapreduce.default.reduce.input.mb=200に示すように、より多くのクラスタリソースを取得します.

Build N-Dimension Cuboid


これらのステップは、レイヤ単位のアルゴリズムの処理プロセスであり、各ステップは、前のステップの出力を入力として使用し、ある次元を除去して集約し、サブcuboidを生成する.例えば、cuboid ABCDの場合、除去次元Aはcuboid BCDを得ることができ、除去次元Bはcuboid ACDなどを得ることができる.
いくつかのcuboidは、1つ以上の親cuboidを集約することによって作成することができ、この場合、Kylinは最小の親cuboidを選択します.例えば、ABはABC(id:1101)とABD(id:1101)の集約によって生成することができ、ABDは、ABCよりも小さいため、親cuboidとして使用される.以上の処理に基づいて,Dの基数が小さいと,今回の集約操作には小さな代価がかかる.したがって、cubeのrowkey順序を設計する場合は、低基数の次元列を末尾に置くことを覚えておいてください.これは、cubeの構築プロセスだけでなく、後集約(HBAseで対応するcuboidを検索するプロセスを指すべき)もこのルールに従うため、cubeクエリーにもメリットがあります.
通常、N−Dから(N/2)−Dへの構築プロセスは遅い.これはcuboidが爆発的に成長するプロセスであるからである.N−Dにはcuboidが1個、(N−1)−DにはN個、(N−1)−DにはN個、(N−1)−DにはN*(N−1)個などがある.(N/2)-Dステップの後、構築プロセスはますます速くなります.

Build Cube


このステップはcubeを構築するために新しいアルゴリズムを用いた:ブロック単位アルゴリズム(「in−mem」アルゴリズムとも呼ばれる).このアルゴリズムは、すべてのcuboidを構築するためにMRタスクを1回だけ使用しますが、レイヤ単位のアルゴリズムよりも多くのメモリを消費する必要があります.この手順では、「conf/kylin_job_conf_inmem.xml」の関連する構成項目が使用されます.デフォルトでは、mapperごとに3 Gのメモリが必要です.クラスタに十分なメモリがある場合は、「conf/kylin_job_conf_inmem.xml」で構成を変更してより大きなメモリを取得することで、より多くのデータを処理でき、パフォーマンスも向上します.次のように構成を変更します.
<property>
    <name>mapreduce.map.memory.mbname>
    <value>6144value>
    <description>description>
property>

<property>
    <name>mapreduce.map.java.optsname>
    <value>-Xmx5632mvalue>
    <description>description>
property>

Kylinはデータ分布(cube統計で取得)に基づいて適切なcube構築アルゴリズムを自動的に選択することに注意してください.一般的にどのアルゴリズムを使用するかを表示する必要はありません.

Convert Cuboid Data to HFile


このステップでは、cuboidファイル(シーケンスファイルフォーマット)をHbaseのHFileファイルに変換するMRタスクが開始されます.Kylinはcubeの統計によりHBAseのregion個数を計算し,デフォルトではregionあたり5 Gである.Region数が多ければ多いほど、より多くのreducerが使用されます.reducerの数が少なく、パフォーマンスが悪い場合は、conf/kylin.propertiesで次の構成項目を追加できます.
kylin.hbase.region.cut=2
kylin.hbase.hfile.size.gb=1

HBAseのregionがどれくらい大きいか分からない場合は、HBAse管理者に連絡してください.

Load HFile to HBase Table


このステップでは、HBAse APIを使用してHFileをHBAseのregionにインポートします.このステップは簡単で、すぐに実行できます.

Update Cube Info


Hbaseにデータをインポートすると、Kylinは新しく生成したsegmentのメタデータ内の状態をreadyに変更します.この一歩もとても速いです.

Cleanup


このステップでは、主にHiveからテンポラリ・テーブルを削除します.前のステップでは、segmentの状態がreadyに変更されたため、このステップの操作はsegmentに何の影響も与えません.このステップで実行エラーが発生しても、KylinがStorageCleanupJobを実行している間にすべてのゴミが回収されるので心配する必要はありません.