web-dev-qa-db-ja.com

寄木細工の索引

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

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

私の質問は次のとおりです。いつインデックスがParquetに追加されますか。それを行うための高レベルの設計は何ですか?正しいパーティションを指し示すインデックスに既に満足していると思います。

敬具、

シェールド。

28

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

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

この手法では、ページと行グループのサイズを小さくすることで、より細かいフィルタリングを行うこともできますが、その場合は、エンコードの効率とI/Oの効率を犠牲にします。

30
blue

2018年12月更新

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

https://github.com/Apache/parquet-format/blob/master/CHANGES.md#version-25

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

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

この新機能は列インデックスと呼ばれます。基本的に、Parquetは、Parquetレイアウトに2つの新しい構造、Column IndexとOffset Indexを追加しました。

以下は、それが解決するものと方法のより詳細な技術説明です。

問題ステートメント

現在の形式では、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 in Bytes

そして

Scanner CPU time in ms

ご覧のとおり、一部のクエリでは、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://www.slideshare.net/RyanBlue3/parquet-performance-tuning-the-missing- guide より技術的な実装固有のドキュメント- https://homepages.cwi.nl/~boncz/msc/2018-BoudewijnBraams.pdf

17
Tagar