メインコンテンツまでスキップ

データレーククエリ最適化

このドキュメントでは主に、レイクデータ(Hive、Iceberg、Paimonなど)をクエリする際の最適化手法と戦略について説明します。

Partition Pruning

クエリでパーティション列の条件を指定することで、不要なパーティションをプルーニングし、読み取る必要があるデータ量を削減できます。

EXPLAIN <SQL>を使用してXXX_SCAN_NODEpartitionセクションを確認することで、パーティションプルーニングが有効かどうか、およびこのクエリでスキャンする必要があるパーティション数を確認できます。

例:

0:VPAIMON_SCAN_NODE(88)
table: paimon_ctl.db.table
predicates: (user_id[#4] = 431304818)
inputSplitNum=15775, totalFileSize=951754154566, scanRanges=15775
partition=203/0

Local Data Cache

Data Cacheは、リモートストレージシステム(HDFSまたはオブジェクトストレージ)から最近アクセスされたデータファイルをローカルディスクにキャッシュすることで、同じデータにアクセスする後続のクエリを高速化します。

キャッシュ機能はデフォルトで無効になっています。設定して有効にするには、Data Cacheのドキュメントを参照してください。

バージョン4.0.2以降、cache warmup機能がサポートされており、data cacheをより積極的に活用してクエリパフォーマンスを向上させることができます。

HDFS Read Optimization

HDFS DocumentationHDFS IO Optimizationセクションを参照してください。

Split Count Limit

外部テーブル(Hive、Iceberg、Paimonなど)をクエリする際、Dorisはファイルを複数のsplitに分割して並列処理を行います。一部のシナリオ、特に大量の小さなファイルがある場合、過多なsplitが生成され、以下の問題を引き起こす可能性があります:

  1. メモリ圧迫:過多なsplitは大量のFEメモリを消費します
  2. OOM問題:過度なsplit数はOutOfMemoryErrorを引き起こす可能性があります
  3. パフォーマンス劣化:過多なsplitの管理はクエリプランニングのオーバーヘッドを増加させます

max_file_split_numセッション変数を使用して、テーブルスキャンごとに許可される最大split数を制限できます(4.0.4以降サポート):

  • Type: int
  • Default: 100000
  • Description: 非バッチモードにおいて、過多なsplitによるOOMを防ぐためにテーブルスキャンごとに許可される最大split数。

使用例:

-- Set maximum split count to 50000
SET max_file_split_num = 50000;

-- Disable this limit (set to 0 or negative number)
SET max_file_split_num = 0;

この制限が設定されると、Dorisは分割数が指定された制限を超えないように、最小分割サイズを動的に計算します。

Merge IO最適化

HDFSやオブジェクトストレージなどのリモートストレージシステムに対して、DorisはMerge IO技術を通じてIOアクセスを最適化します。Merge IO技術は本質的に、隣接する複数の小さなIOリクエストを1つの大きなIOリクエストにマージすることで、IOPSを削減し、IOスループットを向上させることができます。

例えば、元のリクエストがファイルfile1の[0, 10]と[20, 50]の部分を読み取る必要がある場合:

Request Range: [0, 10], [20, 50]

Merge IOを通じて、一つのリクエストにマージされます:

Request Range: [0, 50]

この例では、2つのIOリクエストが1つにマージされていますが、追加のデータ(10-20間のデータ)も読み取ります。そのため、Merge IOはIO操作の回数を減らす一方で、潜在的な読み取り増幅の問題をもたらす可能性があります。

Query Profileを通じて具体的なMerge IO情報を確認できます:

- MergedSmallIO:
- MergedBytes: 3.00 GB
- MergedIO: 424
- RequestBytes: 2.50 GB
- RequestIO: 65.555K (65555)

RequestBytesRequestIOは元のリクエストでのデータ量とリクエスト数を示します。MergedBytesMergedIOはマージ後のデータ量とリクエスト数を示します。

MergedBytesRequestBytesよりもはるかに大きいことが分かった場合、深刻な読み取り増幅を示しています。以下のパラメータで調整できます:

  • merge_io_read_slice_size_bytes

    セッション変数で、バージョン3.1.3以降でサポートされています。デフォルトは8MBです。深刻な読み取り増幅が発生している場合、このパラメータを64KBなどに減らして、修正されたIOリクエストとクエリレイテンシが改善されるかを観察できます。

Parquet Page Cache

備考

バージョン4.1.0以降でサポートされています。

Parquet Page CacheはParquetファイル用のページレベルキャッシュメカニズムです。この機能はDorisの既存のPage Cacheフレームワークと統合し、解凍された(または圧縮された)データページをメモリにキャッシュすることで、クエリパフォーマンスを大幅に向上させます。

主要機能

  1. 統合されたPage Cache統合

    • Doris内部テーブルで使用される同一の基盤StoragePageCacheフレームワークを共有
    • メモリプールと退避ポリシーを共有
    • 統合されたパフォーマンス監視のため、既存のキャッシュ統計とRuntimeProfileを再利用
  2. インテリジェントキャッシュ戦略

    • 圧縮率認識: parquet_page_cache_decompress_thresholdパラメータに基づいて、圧縮または解凍されたデータをキャッシュするかを自動的に決定
    • 柔軟なストレージアプローチ: 解凍サイズ / 圧縮サイズ ≤ しきい値の場合は解凍されたデータをキャッシュ;そうでなければ、enable_parquet_cache_compressed_pagesに基づいて圧縮されたデータをキャッシュするかを決定
    • キャッシュキー設計: ファイル変更後のキャッシュ一貫性を確保するため、file_path::mtime::offsetをキャッシュキーとして使用

設定パラメータ

以下はBE設定パラメータです:

  • enable_parquet_page_cache

    Parquet Page Cache機能を有効にするかどうか。デフォルトはfalseです。

  • parquet_page_cache_decompress_threshold

    圧縮または解凍されたデータをキャッシュするかを制御するしきい値。デフォルトは1.5です。解凍サイズ / 圧縮サイズの比率がこのしきい値以下の場合、解凍されたデータがキャッシュされます;そうでなければ、enable_parquet_cache_compressed_pages設定に基づいて圧縮されたデータをキャッシュするかを決定します。

  • enable_parquet_cache_compressed_pages

    圧縮率がしきい値を超える場合に圧縮されたデータページをキャッシュするかどうか。デフォルトはfalseです。

パフォーマンス監視

Query Profileを通じてParquet Page Cacheの使用状況を確認できます:

ParquetPageCache:
- PageCacheHitCount: 1024
- PageCacheMissCount: 128

PageCacheHitCountはキャッシュヒット数を示し、PageCacheMissCountはキャッシュミス数を示します。