前回の記事で、
STORED AS INPUTFORMAT'com.hadoop.mapred.DeprecatedLzoTextInputFormat 'OUTPUTFORMAT'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'ストレージを使用したため、データウェアハウスのodsレイヤーにいると述べたためです。モード、しかし、count(*)統計結果がselect *と異なる状況に遭遇したので、ファイルストレージ形式を詳細に理解し始める必要があります(問題は解決できませんが、少なくとも問題の真実、これを見たいこの記事については、Hive Environment Tuning Encyclopediaにジャンプしてください。ただし、まだ解決されていないバグがあり、これは頭痛の種です!)。
データウェアハウスでは、インターフェイステーブル(他のデータベースからインポートされるか、最終的に他のデータベースにエクスポートされる)を除いて、残りのテーブルのストレージ形式が圧縮形式と一致していることをお勧めします。
まず、Hiveテーブルの現在の主流のストレージ形式と圧縮方法について説明しましょう。
ファイルストレージ形式
Hiveの公式ウェブサイトによると、Apache Hiveは、TextFile(テキスト形式)、RCFile(決定ファイル)、SequenceFile(バイナリシリアル化ファイル)、AVRO、ORC(最適化ランク)形式ファイルなど、ApacheHadoopで使用されるいくつかの使い慣れたファイル形式をサポートしています。現在私たちがそれらのほとんどを使用しているParquet形式は、TextFile、SequenceFile、ORC、およびParquetです。
これら2種類の行列式ストレージを詳しく見てみましょう。
1、ORC
1.1ORCストレージ構造
まず、公式WebサイトからORCストレージモデル図を入手します。
少し複雑に見えるので、少し単純化してみましょう。簡単な図を描いて説明しました
左の図は、行ごとに格納される従来の行ベースのデータベースストレージ方式を示しています。ストレージインデックスがない場合、フィールドにクエリを実行する必要がある場合は、データの行全体を見つけてフィルタリングする必要があります。 。このタイプはIOをより消費します。リソースであるため、Hiveの最初にこの問題を解決するためにインデックスメソッドが使用されました。
ただし、インデックスのコストが高いため、現在のHive 3.Xではインデックスが廃止され、もちろん列型ストレージが長い間導入されてきました。
列ストレージの格納方法は、実際にはその名前と同じで、上の右図に示すように、列ごとに格納されます。このように、フィールドのデータをクエリすると、インデックスクエリと同等になります。 、これは非常に効率的です。ただし、テーブル全体を検索する必要がある場合は、すべての列を取得して個別に要約する必要があるため、より多くのリソースを消費します。そのため、ORC行列式ストレージが登場しました。
1.全表スキャンが必要な
場合は、行グループに従って読み取ることができます。2。列データをフェッチする必要がある場合は、すべての行グループのすべての行ではなく、行グループに基づいて指定された列を読み取ります。 1行内すべてのフィールドのデータ。
ORCストレージの基本的なロジックを理解した後、そのストレージモデル図を見てみましょう。
同時に、以下の詳細なテキストも添付しているので、チェックしてみてください。
- ストライプ:ORCファイルがデータを格納する場所。各ストライプは通常、HDFSのブロックサイズです。(以下の3つの部分が含まれています)
1. index data:保存了所在条带的一些统计信息,以及数据在 stripe中的位置索引信息。
2. rows data:数据存储的地方,由多个行组构成,每10000行构成一个行组,数据以流( stream)的形式进行存储。
3. stripe footer:保存数据所在的文件目录
- ファイルフッター:ファイル内のサイプのリスト、各ストライプの行数、および各列のデータ型が含まれます。また、各列の最小値、最大値、行数、合計などの集計情報も含まれています。
- 追記:圧縮パラメータと圧縮サイズに関する情報が含まれています
したがって、実際には、ORCは、ファイルレベル、ストリップレベル、および行グループレベルの3つのレベルのインデックスを提供することがわかりました。したがって、クエリを実行するときに、これらのインデックスを使用すると、満たされないファイルとデータブロックのほとんどを回避できます。クエリ条件。
ただし、ORC内のすべてのデータの記述情報は、保存されたデータと一緒にまとめられ、外部データベースは使用されないことに注意してください。
特記事項:ORC形式のテーブルはトランザクションACIDもサポートしますが、トランザクションをサポートするテーブルはバケット化されたテーブルである必要があるため、大量のデータを更新するのに適しています。トランザクションを使用して小さなバッチのデータを頻繁に更新することはお勧めしません。
#开启并发支持,支持插入、删除和更新的事务
set hive. support concurrency=truei
#支持ACID事务的表必须为分桶表
set hive. enforce bucketing=truei
#开启事物需要开启动态分区非严格模式
set hive.exec,dynamicpartition.mode-nonstrict
#设置事务所管理类型为 org. apache.hive.q1. lockage. DbTxnManager
#原有的org. apache. hadoop.hive.q1.1 eckmar. DummyTxnManager不支持事务
set hive. txn. manager=org. apache. hadoop. hive. q1. lockmgr DbTxnManageri
#开启在相同的一个 meatore实例运行初始化和清理的线程
set hive. compactor initiator on=true:
#设置每个 metastore实例运行的线程数 hadoop
set hive. compactor. worker threads=l
#(2)创建表
create table student_txn
(id int,
name string
)
#必须支持分桶
clustered by (id) into 2 buckets
#在表属性中添加支持事务
stored as orc
TBLPROPERTIES('transactional'='true‘);
#(3)插入数据
#插入id为1001,名字为student 1001
insert into table student_txn values('1001','student 1001');
#(4)更新数据
#更新数据
update student_txn set name= 'student 1zh' where id='1001';
# (5)查看表的数据,最终会发现id为1001被改为 sutdent_1zh
1.2ORCに関するハイブ構成
テーブル構成プロパティ(テーブルの作成時に構成されますtblproperties ('orc.compress'='snappy');
。例:
- orc.compress:ORCファイルの圧縮タイプを示します。使用可能なタイプはNONE、ZLB、SNAPPYです。デフォルト値はZLIBです(Snappyはスライスをサポートしていません)-この構成が最も重要です。
- orc。compress.Slze:圧縮されたチャンクのサイズを表します。デフォルト値は262144(256KB)です。
- orc。stripe.size:書き込みストライプ、使用可能なメモリバッファプールサイズ。デフォルト値は67108864(64MB)です。
- orc。row。index。stride:行グループレベルのインデックスのデータサイズ。デフォルトは10000であり、10000以上の数値に設定する必要があります。
- orc。createindex:行グループレベルのインデックスを作成するかどうか、デフォルトはtrueです。
- orc。ブルームフィルター。列:ブルームフィルターグループを作成する必要があります。
- orc。ブルームフィルターfpp:Falseブルームフィルターを使用する確率。デフォルト値は0です。
拡張機能:Hiveのブルームフィルターを使用すると、データがファイルスペースの少ないテーブルに格納されているかどうかをすばやく判断できますが、このテーブルに属していないデータがこのテーブルに属していると判断される場合もあります。偽陽性確率と呼ばれる、開発者は確率を調整できますが、確率が低いほど、ブルームフィルターが必要になります
2、寄木細工
上記のORCについて説明した後、行列式ストレージの基本的な理解も得られました。Parquetは、もう1つの高性能な行列式ストレージ構造です。
2.1寄木細工の収納構造
ORCは非常に効率的であるため、なぜ別のParquetが必要なのですか?Parquetは、Hadoopエコシステム内のすべてのプロジェクトで、圧縮された効率的な列データ表現を使用できるようにするためです。圧縮形式(Snappy、GZIP、Lzo)をサポートしています。
Parquet 是语言无关的,而且不与任何一种数据处理框架绑定在一起,适配多种语言和组件,能够与 Parquet 配合的组件有:
查询引擎: Hive, Impala, Pig, Presto, Drill, Tajo, HAWQ, IBM Big SQL
计算框架: MapReduce, Spark, Cascading, Crunch, Scalding, Kite
数据模型: Avro, Thrift, Protocol Buffers, POJOs
寄木細工の収納構造を見てみましょう、最初に公式ウェブサイトを見てください
ええと、少し大きいです、簡単なバージョンを描きます
寄木細工のファイルはバイナリモードで保存されるため、直接読み取ることはできません。ORCと同様に、ファイルのメタデータとデータは一緒に保存されるため、寄木細工の形式のファイルは自己分析型です。
- 行グループ:各行グループには特定の数の行が含まれ、orcのストライプの概念と同様に、少なくとも1つの行グループがHDFSファイルに格納されます。
- 列チャンク:行グループの各列は列ブロックに格納され、行グループのすべての列はこの行グループファイルに連続して格納されます。列ブロックの値はすべて同じタイプであり、異なる列ブロックは異なるアルゴリズムを使用して圧縮される場合があります。
- ページ:各列ブロックは複数のページに分割されます。ページはコーディングの最小単位です。同じ列ブロックの異なるページは、異なるコーディング方法を使用する場合があります。
2.2寄木細工のテーブルの構成プロパティ
- 寄木細工のブロックサイズ:デフォルト値は134217728バイトです。これは128MBで、メモリ内の行グループのブロックサイズを表します。この値を大きな値に設定すると、Parquetファイルの読み取り効率を向上させることができますが、それに応じて、書き込み時に多くのメモリを消費する必要があります。
- parquet。page:size:デフォルト値は1048576byt、つまり1MBで、これは各ページ(ページ)のサイズを意味します。これは特に圧縮されたページサイズを指し、ページデータは読み取り時に最初に解凍されます。ページはParquetの操作データの最小単位です。データにアクセスする前に、データを読み取るたびにページ全体を読み取る必要があります。この値の設定が小さすぎると、圧縮中にパフォーマンスの問題が発生します
- parquet。compression:デフォルト値はUNCOMPRESSEDで、これはページ圧縮方法を意味します。使用可能な圧縮方法は、UNCOMPRESSED、SNAPPY、GZP、およびLZOです。
- Parquetenable。dictionary:デフォルトはtueで、辞書エンコードを有効にするかどうかを示します。
- 寄木細工の辞書page.size:デフォルト値は1048576バイト、つまり1MBです。辞書エンコーディングを使用する場合、Parquetの各行と列に辞書ページが作成されます。辞書圧縮を使用すると、保存されたデータページに重複データが多数ある場合、優れた圧縮効果が得られ、各ページのメモリ使用量を削減することもできます。
3.ORCと寄木細工の比較
同時に、「Hive Performance Tuning」の作者の場合から、ORCとParquetストレージ形式の2つのテーブルをインポートし、同じデータをインポートしてSQLクエリを実行したところ、ORCを使用して行が読み取られたことがわかりました。はParquetよりもはるかに小さかったため、ORCを使用しました。ストレージとして、メタデータを使用して不要なデータをより多く除外でき、クエリに必要なクラスターリソースはParquetよりも少なくなります。(より詳細なパフォーマンス分析については、https://blog.csdn.net/yu616568/article/details/51188479に移動してください)
したがって、ORCはストレージの点で依然として見栄えがします
圧縮方法
フォーマット | 分割可能 | 平均圧縮速度 | テキストファイルの圧縮効率 | Hadoop圧縮コーデック | 純粋なJavaの実装 | 原生 | 備考 |
gzip | 番号 | 速い | 高い | org.apache.hadoop.io.compress.GzipCodec | はい | はい | |
lzo | はい(使用するライブラリによって異なります) | とても早い | 中 | com.hadoop.compression.lzo.LzoCodec | はい | はい | 各ノードにLZOをインストールする必要があります |
bzip2 | はい | スロー | すごく高い | org.apache.hadoop.io.compress.Bzip2Codec | はい | はい | 分割可能なバージョンには純粋なJavaを使用する |
zlib | 番号 | スロー | 中 | org.apache.hadoop.io.compress.DefaultCodec | はい | はい | Hadoopのデフォルトの圧縮コーデック |
スナッピー | 番号 | とても早い | 低 | org.apache.hadoop.io.compress.SnappyCodec | 番号 | はい | Snappyには純粋なJavaポートがありますが、Spark / Hadoopでは使用できません。 |
ストレージと圧縮の組み合わせを選択するにはどうすればよいですか?
ORCと寄木細工の要件に応じて、一般的に利用可能
1. ORC形式のストレージ、Snappy圧縮
create table stu_orc(id int,name string)
stored as orc
tblproperties ('orc.compress'='snappy');
2.寄木細工のフォーマットのストレージ、Lzo圧縮
create table stu_par(id int,name string)
stored as orc
tblproperties ('parquet.compression'='lzo');
3.寄木細工のフォーマットのストレージ、Snappy圧縮
create table stu_par(id int,name string)
stored as orc
tblproperties ('parquet.compression'='snappy');
HiveのSQLはMRタスクに変換されるため、ファイルがORCに保存され、Snappyによって圧縮される場合、Snappyはファイル分割をサポートしないため、圧縮ファイルは1つのタスクによってのみ読み取られます。圧縮ファイルが大きい場合は、通常のファイルのマップを読み取るよりも、ファイルのマップを処理する方がはるかに時間がかかります。これは、よく言われるマップ読み取りファイルのデータスキューです。
この状況を回避するには、データを圧縮するときにbzip2やZipなどのファイルセグメンテーションをサポートする圧縮アルゴリズムを使用する必要があります。しかし、まさにORCが今述べた圧縮方法をサポートしていないので、データの偏りを避けるために大きなファイルに遭遇する可能性があるときにORCを選択しない理由になっています。
Hve on Sparkアプローチでも同じことが言えます。分散アーキテクチャとして、Sparkは通常、複数の異なるマシンから一緒にデータを読み取ろうとします。この状況を実現するには、各作業ノードが新しいレコードの先頭を検出できる必要があります。これには、ファイルを分割できる必要がありますが、分割できない一部の圧縮ファイルでは、単一のノードを使用してすべてのデータを読み取る必要があります。 。これは、パフォーマンスのボトルネックを簡単に引き起こす可能性があります。(次の記事では、Spark読み取りファイルのソースコード分析について詳しく説明しています)
したがって、実際の本番環境では、Parquetストレージとlzo圧縮を使用するのが一般的です。この場合、分割できない大きなファイルの読み取りに起因するデータの偏りを回避できます。
ただし、データ量が多くない場合(数Gを超える大きなファイルはないと予測されます)、ORCストレージを使用すると、スナッピーな圧縮効率は依然として非常に高くなります。