Sparkチェックorc形式のハイブデータエラーNullPointerException
Spark Check Orc Format Hive Data Error Nullpointerexception
val df: DataFrame = sqlContext.sql('select vipId,brandId,dt from pro60050.browse_wxapp_page_dt_partition where dt >= 20200227 and brandId = 253') df.show()
insert overwrite table pro60050.browse_wxapp_page_dt_partition partition(dt=20200227) select `(dt)?+.+` from hivedb.hiveTableName where dt=20200227 and brandId in (253)
set hive.exec.orc.split.strategy=ETL
問題分析:Baidu、google
1インスピレーションと: https://blog.csdn.net/wuzhilon88/article/details/100524131 この記事
2次に、テーブル構造を確認します。実際、orc形式です。
pro60050.browse_wxapp_page_dt_partition
3パーティション内の空のファイルがあるディレクトリを検索します
パーティションディレクトリに空のファイルがあります
0 /usr/hive/warehouse/pro60050.db/browse_wxapp_page_dt_partition/dt=20200227/000000_0
0 /usr/hive/warehouse/pro60050.db/browse_wxapp_page_dt_partition/dt=20200227/000001_0
0 /usr/hive/warehouse/pro60050.db/browse_wxapp_page_dt_partition/dt=20200227/000002_0
4次の表でデータインポートのロジックをトレースします。
挿入上書きのハイブステートメントを見つけ、これが静的パーティションテーブルであることがわかりました。パーティションにデータを挿入するときは、最初にパーティションを指定してください
SparkSQL reports the following error when reading hive table data My statement is very simple as follows:
また、元のテーブル(hivedb.hiveTableName)には、20200227日のデータに、他のブランドIDに対応する多くのデータがあります。したがって、selectを使用すると、3つのマップが開始され、ブランド253のデータがたまたまこれである20200227日目1日で253のデータがないため、3つのマップのみが3つの空のファイルに対応します。
5挿入上書きステートメントで空のファイルが生成されないようにしてください。
失敗:この空のファイルは、マップの数に応じて生成された小さなファイルです。選択クエリを開始すると必ずMRが開始されるため、マップフェーズを回避することはできません。
6空のファイルの計算は避けられません。そこで、スパークコードでハイブデータの読み取り戦略を設定して制御します
同僚と協力して、この問題を解決する方法を見つけてください。
問題はパーティション内の空のファイルが原因であることが判明しました。次に、空のファイルの読み取りの問題を解決してください。
私の状況に合った記事があります:
https://www.cnblogs.com/barneywill/p/10142244.html
HYBRIDモードは、予想されるマッパー数よりもファイルが少ない場合はすべてのファイルのフッターを読み取り、平均ファイルサイズがデフォルトのHDFSブロックサイズよりも小さい場合は、ファイルごとに1つの分割を生成するように切り替えます。 ETLストラテジーは、スプリットを生成する前に常にORCフッターを読み取りますが、BIストラテジーは、HDFSからデータを読み取らずに、ファイルごとのスプリットを高速に生成します。
HYBRIDで満たされない場合、hive.exec.orc.split.strategyはデフォルトでHYBRIDになっていることがわかります。
if(avgFileSize> context.maxSize){
その後
splitStrategy = new BISplitStrategy(context、fs、dir、children、isOriginal、deltas、
カバー)
つまり、デフォルトはHYBRIDモード(混合モード読み取り)です。読み取られたデータの量がhdfsデータブロックのブロックサイズよりも少ない場合、ファイルの数に応じて各ファイルのカットを生成するために直接使用されます(このパーティションのデータはブロックサイズに達しないため、 1つのファイルを1つずつ読み取る方法なので、空のファイルが報告されます原因:java.lang.NullPointerExceptionこの例外)。読み取られるデータの量がブロックのデフォルトのブロックサイズよりも大きい場合、データはブロックに従ってセグメンテーションされた後に読み取られます。
データを読み取るための戦略を理解し、混合モードを回避するように設定します。ファイルに基づく読み取りではなく、ファイルサイズに基づく分割読み取りを使用する
|_+_|
実際のコードは次のように設定されています。
その後、問題は解決されます
補足:
hive.exec.orc.split.strategyパラメーターは、ORCテーブルを読み取るときに分割を生成するための戦略を制御します。 BIストラテジーは、分割分割の粒度としてファイルを使用しますETLストラテジーは、ファイルを複数のストライプに分割して、スプリットHYBRIDストラテジーを形成します。平均ファイルサイズがhadoopの最大スプリット値(デフォルトは256 * 1024 * 1024)ETLストラテジーよりも大きい場合に使用し、それ以外の場合は使用します。 BI戦略。 ---一部の大きなORCテーブルでは、フッターが大きくなる可能性があり、ETL戦略により、hdfsから大量のデータをプルして分割を分割し、ドライバー側でOOMを引き起こす可能性があります。したがって、そのようなテーブルを読み取るための提案は、BI戦略を使用します。特にデータスキューのある小さなテーブルの場合(ここでのデータスキューとは、いくつかのファイルに格納されている多数のストライプを指します)、ETL戦略を使用することをお勧めします。 ---さらに、spark.hadoop.mapreduce.input.fileinputformat.split.minsizeパラメーターは、ORC分割中のストライプのマージを制御できます。特定のロジックは、いくつかのストライプのサイズがspark.hadoop.mapreduce.input.fileinputformat.split.minsizeよりも小さい場合、それらは処理のために1つのタスクに結合されるというものです。この値を適切に調整して、ORCテーブルの読み取りの同時実行性を高めることができます。