何十億ものレコードを保持するHiveテーブルがあり、その時系列データであるため、パーティションは1分あたりです。 1分あたり約100万件のレコードがあります。
テーブルにいくつかのフィールドがあります。VIN番号(17文字)、ステータス(2文字)...など
したがって、Varchar(X)とStringを使用することを選択した場合、テーブルの作成中に質問があります。ストレージまたはパフォーマンスの問題はありますか?
Varcharのいくつかの制限は https://cwiki.Apache.org/confluence/display/Hive/LanguageManual+Types#LanguageManualTypes-string
「x」文字を超える文字を指定すると、サイレントに切り捨てられるため、文字列を保持することは将来の証拠になります。
非ジェネリックUDFは、varchar型を入力引数または戻り値として直接使用することはできません。代わりに文字列UDFを作成でき、varchar値は文字列に変換されてUDFに渡されます。 varchar引数を直接使用するか、varchar値を返すには、GenericUDFを作成します。
型情報を取得するためにリフレクションベースのメソッドに依存している場合、varcharをサポートしない他のコンテキストが存在する可能性があります。これには、いくつかのSerDe実装が含まれます。
ストレージとパフォーマンスの観点から、varcharの代わりにstringを使用するために支払う必要のあるコストはいくらですか
APIでどのように実装されているかを理解してみましょう:-
org.Apache.hadoop.Hive.ql.io.parquet.write.DataWritableWriter
これが魔法の始まりです->
private DataWriter createWriter(ObjectInspector inspector, Type type) {
case stmt.....
........
case STRING:
return new StringDataWriter((StringObjectInspector)inspector);
case VARCHAR:
return new VarcharDataWriter((HiveVarcharObjectInspector)inspector);
}
dataWritableWriterクラスのcreateWriterメソッドは、列のデータ型をチェックします。つまり、varchar
またはstring
のいずれかであるため、これらのタイプのライタークラスが作成されます。
それでは、VarcharDataWriter
クラスに移りましょう。
private class VarcharDataWriter implements DataWriter {
private HiveVarcharObjectInspector inspector;
public VarcharDataWriter(HiveVarcharObjectInspector inspector) {
this.inspector = inspector;
}
@Override
public void write(Object value) {
String v = inspector.getPrimitiveJavaObject(value).getValue();
recordConsumer.addBinary(Binary.fromString(v));
}
}
[〜#〜]または[〜#〜]
StringDataWriter
クラスへ
private class StringDataWriter implements DataWriter {
private StringObjectInspector inspector;
public StringDataWriter(StringObjectInspector inspector) {
this.inspector = inspector;
}
@Override
public void write(Object value) {
String v = inspector.getPrimitiveJavaObject(value);
recordConsumer.addBinary(Binary.fromString(v));
}
}
addBinary両方のクラスのメソッドは、実際にはエンコードされたデータ型(encodeUTF8エンコード)のバイナリ値を追加します。また、文字列のエンコードは、varcharのエンコードとは異なります。
質問への短い答え:-文字列とvarcharのUnicodeエンコーディングは異なります。ストレージに関しては、番号によってほとんど変わらない場合があります。ストアのバイト数。しかし、私の理解によると、パフォーマンスに関しては、Hiveはschema on read
ツール。 ParquetRecordReader
はレコードの読み取り方法を知っています。バイトを読み取るだけなので、varcharまたはstringデータ型によるパフォーマンスの違いはありません。
最良の方法は、文字列を使用することです。 varcharも内部的に文字列として格納されます。確実にデータ型を作成する場合は、必要に応じて同じデータの上にビューを作成します。
T私が見る唯一の違いは、Stringは最大値32,767バイトで無制限であり、Varcharは制限されていることです。文字列は、データを使用していない場合、データを効率的に制限します。
文字列では、ベクトル化のサポートも利用できます。
私の場合は、ORC形式がHiveストレージのデフォルトの標準になることを考慮して、この議論を制限し、焦点を当てることになります。パフォーマンスは、Hive自体のVARCHARとSTRINGの間の問題ではないと思います。データのエンコード(以下のリンクを参照)は、ORC形式に関してはどちらの場合も同じです。これは、カスタムSerdeを使用している場合でも適用され、すべてSTRINGとして扱われ、エンコードが適用されます。
私にとっての本当の問題は、STRINGが他のサードパーティのツールやプログラミング言語によってどのように消費されるかということです。最終用途にSTRINGに関する文書化された問題がない場合は、VARCHAR(n)型よりも型としてSTRINGを使用して簡単に進めることができます。これは、パイプラインを介して要素をマッピングする必要があり、サイズエラーが無視されるリスクを冒したくないETLを操作する場合に特に便利です。サードパーティのツールに戻ると、たとえばSASは、Hiveに接続したときにSTRING型を読み取る際に文書化された問題がいくつかあります。これは、一部の人にとっては問題の領域になり、一部の人にとっては問題になるでしょう。たとえば、JDBCまたはODBCを介してHiveに接続する場合、データベースはデータをVARCHAR(max)として読み取る可能性があります。これは、考慮する必要のある課題の数を意味する場合があります。
これを、Hive自体のパフォーマンスではなく、主要な要因と見なすことをお勧めします。使用するタイプを決定するためにVARCHARがSTRINGよりも優れていることを示唆するものはこれまでにありません。
もう1つのポイントは、VARCHARがベクトル化をサポートするようになったことです。いずれの場合も、VARCHARを受け取るUDFはSTRINGと見なされるため、ポイントは否定されます。
理解が違う場合に備えて訂正していただきありがとうございます。また、役立つ可能性のある参照リンクを提供できます。