41

Parquet テーブルで高速範囲クエリを実行できるようにしたいと考えています。返されるデータの量は合計サイズに比べて非常に小さいですが、フル カラム スキャンを実行する必要があるため、私のユース ケースには遅すぎます。

インデックスを使用するとこの問題が解決され、これは Parquet 2.0 で追加される予定であると読みました。ただし、これに関する他の情報を見つけることができないため、そうではなかったと推測しています。データがソートされている場合、(複数列の) インデックスの追加を妨げる根本的な障害があるとは思いません。私の場合はそうです。

私の質問は、いつインデックスが Parquet に追加されるのですか? また、そのための高レベルの設計はどのようなものですか? 正しいパーティションを示すインデックスがあれば、私はすでに満足していると思います。

敬具、

シェルド。

4

2 に答える 2

41

2018年12月更新

Parquet Format バージョン 2.5 では、列インデックスが追加されました。

https://github.com/apache/parquet-format/blob/master/CHANGES.md#version-250

この新機能のサブタスクのリストについては、 https://issues.apache.org/jira/browse/PARQUET-1201を参照してください。

この機能は Parquet 形式自体にマージされたばかりであり、さまざまなバックエンド (Spark、Hive、Impala など) がサポートを開始するには時間がかかることに注意してください。

この新機能は列インデックスと呼ばれます。基本的に、Parquet は寄木細工のレイアウトに 2 つの新しい構造 (列インデックスとオフセット インデックス) を追加しました。

以下は、それが何をどのように解決するかについて、より詳細な技術的説明です。

問題文

現在の形式では、ColumnMetaData の ColumnChunks と DataPageHeader 構造体内の個々のページの統計が格納されます。ページを読み取るとき、統計に基づいてページをスキップできるかどうかを判断するために、リーダーはページ ヘッダーを処理する必要があります。これは、リーダーが列内のすべてのページにアクセスする必要があることを意味し、ディスクからほとんどの列データを読み取る可能性があります。

目標

最小値と最大値に基づいてページに直接アクセスできるようにすることで、範囲スキャンとポイント ルックアップの両方の I/O を効率化します。特に:

  1. 行グループの並べ替え列に基づく行グループ内の単一行のルックアップでは、取得された列ごとに 1 つのデータ ページのみが読み取られます。並べ替え列の範囲スキャンは、関連するデータを含む正確なデータ ページを読み取るだけで済みます。
  2. 他の選択的スキャンの I/O を効率化する: 非ソート列に非常に選択的な述語がある場合、他の取得された列については、一致する行を含むデータ ページにのみアクセスする必要があります。
  3. 選択的述語を使用しないスキャン (行全体のグループ スキャンなど) では、追加のデコード作業は必要ありません。リーダーがインデックス データを読み取る必要がないと判断した場合、オーバーヘッドは発生しません。
  4. 並べ替えられた列のインデックス ページは、ページ間の境界要素のみを格納することで最小限のストレージを使用します。

非目標

セカンダリ インデックスに相当するもの、つまり、ソートされていないデータに対してキー値でソートされたインデックス構造のサポート。

技術的アプローチ

行グループ メタデータに 2 つの新しい列ごとの構造を追加します。 ColumnIndex: これにより、列の値に基づいて列のページへのナビゲーションが可能になり、スキャン述語の一致する値を含むデータ ページを見つけるために使用されます。 OffsetIndex: これにより、ナビゲーションが可能になります。行インデックスであり、ColumnIndex を介して一致として識別された行の値を取得するために使用されます。列の行がスキップされると、他の列の対応する行をスキップする必要があります。したがって、RowGroup の各列の OffsetIndexes はまとめて格納されます。

新しいインデックス構造は、RowGroup とは別に、フッターの近くに格納されるため、リーダーは、選択的スキャンを実行していない場合、それらを読み取るための I/O および逆シリアル化のコストを支払う必要はありません。インデックス構造の場所と長さは、ColumnChunk と RowGroup に格納されます。

Cloudera の Impala チームは、この新機能についていくつかのテストを行いました (Apache Impala コア製品の一部としてはまだ利用できません)。パフォーマンスの向上は次のとおりです。

HDFS I/O (バイト単位)

スキャナーの CPU 時間 (ミリ秒)

ご覧のとおり、一部のクエリでは、CPU 時間とディスクから読み取る必要のあるデータ量の両方が大幅に改善されました。

2016年からの元の回答

struct IndexPageHeader {
  /** TODO: **/
}

https://github.com/apache/parquet-format/blob/6e5b78d6d23b9730e19b78dceb9aac6166d528b8/src/main/thrift/parquet.thrift#L505

現時点では、インデックス ページ ヘッダーは実装されていません。

上記の Parquet 形式のソース コードを参照してください。現在、Parquet 2.0 でも表示されません。

しかし、はい - 擬似インデックス作成機能 (ブルーム フィルター) があるという上記の Parquet に関する Ryan Blue からの優れた回答です。

詳細に興味がある場合は、Parquet ブルーム フィルターと述語のプッシュダウンのしくみに関する優れたドキュメントをお勧めし ます。実装固有のドキュメント - https://homepages.cwi.nl/~boncz/msc/2018-BoudewijnBraams.pdf

于 2016-11-21T06:49:36.750 に答える
40

現在、Parquet は各データ ページの最小/最大統計を保持しています。データ ページは、1 つの列に対して最大 1 MB の値 (エンコード後) のグループです。複数のページは、 Parquet の列チャンクを構成するものです。

これらの最小値/最大値は、列チャンクとチャンクを構成するページの両方をフィルタリングするために使用されます。したがって、フィルター処理する列でレコードを並べ替えてから、データを Parquet に書き込むことで、クエリ時間を改善できるはずです。そうすれば、統計フィルタリングを最大限に活用できます。

ページと行グループのサイズを減らすことで、この手法を使用してより詳細なフィルタリングを行うこともできますが、エンコード効率と I/O 効率はトレードオフになります。

于 2015-05-21T22:57:29.513 に答える