データレーククエリ最適化
この文書は主にレイクデータ(Hive、Iceberg、Paimon等)のクエリ最適化手法と戦略について説明します。
Partition Pruning
クエリでパーティションカラム条件を指定することで、不要なパーティションをプルーニングし、読み取る必要があるデータ量を削減できます。
EXPLAIN <SQL>を使用してXXX_SCAN_NODEのpartitionセクションを確認することで、パーティションプルーニングが有効かどうか、およびこのクエリでスキャンする必要があるパーティション数を確認できます。
例えば:
0:VPAIMON_SCAN_NODE(88)
table: paimon_ctl.db.table
predicates: (user_id[#4] = 431304818)
inputSplitNum=15775, totalFileSize=951754154566, scanRanges=15775
partition=203/0
ローカルデータキャッシュ
Data Cacheは、リモートストレージシステム(HDFSまたはオブジェクトストレージ)から最近アクセスされたデータファイルをローカルディスクにキャッシュすることで、同じデータにアクセスする後続のクエリを高速化します。
キャッシュ機能はデフォルトで無効になっています。設定と有効化については、Data Cacheドキュメントを参照してください。
バージョン4.0.2以降、cache warmup機能がサポートされており、データキャッシュをより積極的に活用してクエリパフォーマンスを向上させることができます。
HDFS読み取り最適化
HDFSドキュメントのHDFS IO最適化セクションを参照してください。
Split数制限
外部テーブル(Hive、Iceberg、Paimonなど)をクエリする際、Dorisはファイルを複数のsplitに分割して並列処理を行います。特に小さなファイルが大量にある場合など、一部のシナリオでは過剰なsplitが生成され、以下の問題が発生する可能性があります:
- メモリ圧迫:過剰なsplitが大量のFEメモリを消費する
- OOM問題:過剰なsplit数がOutOfMemoryErrorを引き起こす可能性がある
- パフォーマンス劣化:過剰なsplitの管理によりクエリ計画のオーバーヘッドが増加する
テーブルスキャンごとに許可される最大split数を制限するために、max_file_split_numセッション変数を使用できます(4.0.4以降でサポート):
- タイプ:
int - デフォルト:
100000 - 説明:非バッチモードにおいて、過剰な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を通じて、1つのリクエストにマージされます:
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)
RequestBytes と RequestIO は、元のリクエストにおけるデータ量とリクエスト数を示します。MergedBytes と MergedIO は、マージ後のデータ量とリクエスト数を示します。
MergedBytes が RequestBytes よりもはるかに大きいことが判明した場合、深刻な読み取り増幅が発生していることを示します。以下のパラメータを通じて調整できます:
-
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フレームワークと統合され、解凍された(または圧縮された)データページをメモリにキャッシュすることで、クエリパフォーマンスを大幅に向上させます。
主な機能
-
統合Page Cache統合
- Doris内部テーブルで使用される同じ基盤の
StoragePageCacheフレームワークを共有 - メモリプールと削除ポリシーを共有
- 統合パフォーマンス監視のため、既存のキャッシュ統計とRuntimeProfileを再利用
- Doris内部テーブルで使用される同じ基盤の
-
インテリジェントキャッシング戦略
- 圧縮率認識:
parquet_page_cache_decompress_thresholdパラメータに基づいて、圧縮データまたは解凍データのどちらをキャッシュするかを自動的に決定 - 柔軟なストレージアプローチ:
解凍サイズ / 圧縮サイズ ≤ 閾値の場合は解凍データをキャッシュ;そうでない場合は、enable_parquet_cache_compressed_pagesに基づいて圧縮データをキャッシュするかどうかを決定 - キャッシュキー設計:
file_path::mtime::offsetをキャッシュキーとして使用し、ファイル変更後のキャッシュ一貫性を保証
- 圧縮率認識:
設定パラメータ
以下はBE設定パラメータです:
-
enable_parquet_page_cacheParquet Page Cache機能を有効にするかどうか。デフォルトは
false。 -
parquet_page_cache_decompress_threshold圧縮データまたは解凍データのどちらをキャッシュするかを制御する閾値。デフォルトは
1.5。解凍サイズ / 圧縮サイズの比率がこの閾値以下の場合、解凍データがキャッシュされます;そうでない場合は、enable_parquet_cache_compressed_pages設定に基づいて圧縮データをキャッシュするかどうかを決定します。 -
enable_parquet_cache_compressed_pages圧縮率が閾値を超える場合に圧縮データページをキャッシュするかどうか。デフォルトは
true。
パフォーマンス監視
Query Profileを通じてParquet Page Cacheの使用状況を確認できます:
ParquetPageCache:
- PageCacheHitCount: 1024
- PageCacheMissCount: 128
PageCacheHitCountはキャッシュヒット数を示し、PageCacheMissCountはキャッシュミス数を示します。