クエリプロファイルは、すべてのクエリについてノードごとの実行詳細をキャプチャします。これらを使用して、パフォーマンスのボトルネックを特定し、クエリのパフォーマンスを最適化します。
クエリプロファイルの有効化
プロファイルの収集を開始するには、変数 enable_profile を設定します。
SET enable_profile=true;enable_profile を true に設定すると、SelectDB は実行されるすべてのクエリに対してプロファイルを生成します。各プロファイルは、すべてのノードにわたる実行詳細を記録します。クエリプロファイルの表示
SHOW QUERY PROFILE 文は、SelectDB Core のバージョン V4.0.0 より前 のものでのみサポートされています。SelectDB Core V4.0.0 以降では、SelectDB コンソールからクエリプロファイルをプレビューまたはダウンロードするか、HTTP API を使用してください。詳細については、「クエリ監査機能の使用」および「クエリプロファイルのエクスポート」をご参照ください。
保存されているすべてのプロファイルを一覧表示するには、次の文を実行します。
SHOW QUERY PROFILE "/"\G;結果の各行は、1 つのプロファイルに対応します。
SHOW QUERY PROFILE "/"\G
*************************** 1. row ***************************
Profile ID: c257c52f93e149ee-ace8ac14e8c9fef9
Task Type: QUERY
Start Time: 2021-04-08 11:30:50
End Time: 2021-04-08 11:30:50
Total: 9ms
Task State: EOF
User: root
Default Db: default_cluster:db1
Sql Statement: select tbl1.k1, sum(tbl1.k2) from tbl1 join tbl2 on tbl1.k1 = tbl2.k1 group by tbl1.k1 order by tbl1.k1Query ID および query_id フィールドはプロファイル ID を指します。クエリプロファイルの分析
クエリのパフォーマンスボトルネックを特定するには、次の 3 ステップのワークフローを使用します。各ステップで、実行階層を 1 レベル深く掘り下げます。
ステップ 1:最も遅いフラグメントの特定
目標:どのフラグメントが主要なボトルネックであるかを見つけます。
実行計画ツリーは、フラグメント構造と各フラグメントの実行時間を示します。各送信者ノードの MaxActiveTime の値は、そのフラグメント内のすべての実行ユニットの中で最も長い実行時間です。
SHOW QUERY PROFILE "/<profile_id>"\G出力例:
SHOW QUERY PROFILE "/c257c52f93e149ee-ace8ac14e8c9fef9"\G
*************************** 1. row ***************************
Fragments:
┌──────────────────────┐
│[-1: DataBufferSender]│
│Fragment: 0 │
│MaxActiveTime: 6.626 ms│
└──────────────────────┘
│
┌──────────────────┐
│[9: EXCHANGE_NODE]│
│Fragment: 0 │
└──────────────────┘
│
┌──────────────────────┐
│[9: DataStreamSender] │
│Fragment: 1 │
│MaxActiveTime: 5.449 ms│
└──────────────────────┘
│
┌──────────────┐
│[4: SORT_NODE]│
│Fragment: 1 │
└──────────────┘
┌┘
┌─────────────────────┐
│[8: AGGREGATION_NODE]│
│Fragment: 1 │
└─────────────────────┘
└┐
┌──────────────────┐
│[7: EXCHANGE_NODE]│
│Fragment: 1 │
└──────────────────┘
│
┌──────────────────────┐
│[7: DataStreamSender] │
│Fragment: 2 │
│MaxActiveTime: 3.505 ms│
└──────────────────────┘
┌┘
┌─────────────────────┐
│[3: AGGREGATION_NODE]│
│Fragment: 2 │
└─────────────────────┘
│
┌───────────────────┐
│[2: HASH_JOIN_NODE]│
│Fragment: 2 │
└───────────────────┘
┌────────────┴────────────┐
┌──────────────────┐ ┌──────────────────┐
│[5: EXCHANGE_NODE]│ │[6: EXCHANGE_NODE]│
│Fragment: 2 │ │Fragment: 2 │
└──────────────────┘ └──────────────────┘
│ │
┌─────────────────────┐ ┌────────────────────────┐
│[5: DataStreamSender]│ │[6: DataStreamSender] │
│Fragment: 4 │ │Fragment: 3 │
│MaxActiveTime: 1.87 ms│ │MaxActiveTime: 636.767 us│
└─────────────────────┘ └────────────────────────┘
│ ┌┘
┌───────────────────┐ ┌───────────────────┐
│[0: OLAP_SCAN_NODE]│ │[1: OLAP_SCAN_NODE]│
│Fragment: 4 │ │Fragment: 3 │
└──────────────────┘ └──────────────────┘
│ │
┌─────────────┐ ┌─────────────┐
│[OlapScanner]│ │[OlapScanner]│
│Fragment: 4 │ │Fragment: 3 │
└─────────────┘ └─────────────┘
│ │
┌─────────────────┐ ┌─────────────────┐
│[SegmentIterator]│ │[SegmentIterator]│
│Fragment: 4 │ │Fragment: 3 │
└─────────────────┘ └─────────────────┘
1 row in set (0.02 sec)この例では、フラグメント 1 の MaxActiveTime が最も高く (5.449 ms)、これが主要なボトルネックです。フラグメント 1 を対象にステップ 2 に進みます。
ステップ 2:最も遅い実行ユニットの特定
目標:ボトルネックとなっているフラグメント内で、最も時間がかかっているノードインスタンスを見つけます。
最も遅いフラグメントを特定した後、その中のすべての実行ユニット (インスタンス) を一覧表示します。
SHOW QUERY PROFILE "/<profile_id>/<fragment_id>";フラグメント 1 の出力例:
SHOW QUERY PROFILE "/c257c52f93e149ee-ace8ac14e8c9fef9/1";
+-----------------------------------+-------------------+------------+
| Instances | Host | ActiveTime |
+-----------------------------------+-------------------+------------+
| c257c52f93e149ee-ace8ac14e8c9ff03 | 10.200.00.01:9060 | 5.449ms |
| c257c52f93e149ee-ace8ac14e8c9ff05 | 10.200.00.02:9060 | 5.367ms |
| c257c52f93e149ee-ace8ac14e8c9ff04 | 10.200.00.03:9060 | 5.358ms |
+-----------------------------------+-------------------+------------+ActiveTime が最も高いインスタンスが、ステップ 3 の対象となります。
ステップ 3:オペレーターごとのメトリクスの調査
目標:対象の実行ユニットで最も時間とリソースを消費しているオペレーターを特定します。
SHOW QUERY PROFILE "/<profile_id>/<fragment_id>/<instance_id>"\Gフラグメント 1 のインスタンス c257c52f93e149ee-ace8ac14e8c9ff03 の出力例:
SHOW QUERY PROFILE "/c257c52f93e149ee-ace8ac14e8c9fef9/1/c257c52f93e149ee-ace8ac14e8c9ff03"\G
*************************** 1. row ***************************
Instance:
┌───────────────────────────────────────┐
│[9: DataStreamSender] │
│(Active: 37.222 us, non-child: 0.40) │
│ - Counters: │
│ - BytesSent: 0.00 │
│ - IgnoreRows: 0 │
│ - OverallThroughput: 0.0 /sec │
│ - PeakMemoryUsage: 8.00 KB │
│ - SerializeBatchTime: 0ns │
│ - UncompressedRowBatchSize: 0.00 │
└───────────────────────────────────────┘
└┐
│
┌──────────────────────────────────┐
│[4: SORT_NODE] │
│(Active: 5.421 ms, non-child: 0.71)│
│ - Counters: │
│ - PeakMemoryUsage: 12.00 KB │
│ - RowsReturned: 0 │
│ - RowsReturnedRate: 0 │
└──────────────────────────────────┘
┌┘
│
┌───────────────────────────────────┐
│[8: AGGREGATION_NODE] │
│(Active: 5.355 ms, non-child: 10.68)│
│ - Counters: │
│ - BuildTime: 3.701us │
│ - GetResultsTime: 0 ns │
│ - HTResize: 0 │
│ - HTResizeTime: 1.211 us │
│ - HashBuckets: 0 │
│ - HashCollisions: 0 │
│ - HashFailedProbe: 0 │
│ - HashFilledBuckets: 0 │
│ - HashProbe: 0 │
│ - HashTravelLength: 0 │
│ - LargestPartitionPercent: 0 │
│ - MaxPartitionLevel: 0 │
│ - NumRepartitions: 0 │
│ - PartitionsCreated: 16 │
│ - PeakMemoryUsage: 34.02 MB │
│ - RowsProcessed: 0 │
│ - RowsRepartitioned: 0 │
│ - RowsReturned: 0 │
│ - RowsReturnedRate: 0 │
│ - SpilledPartitions: 0 │
└───────────────────────────────────┘
└┐
│
┌──────────────────────────────────────────┐
│[7: EXCHANGE_NODE] │
│(Active: 4.360 ms, non-child: 46.84) │
│ - Counters: │
│ - BytesReceived: 0.00 │
│ - ConvertRowBatchTime: 387 ns │
│ - DataArrivalWaitTime: 4.357 ms │
│ - DeserializeRowBatchTimer: 0 ns │
│ - FirstBatchArrivalWaitTime: 4.356 ms│
│ - PeakMemoryUsage: 0.00 │
│ - RowsReturned: 0 │
│ - RowsReturnedRate: 0 │
│ - SendersBlockedTotalTimer(*): 0 ns │
└──────────────────────────────────────────┘ノードの Active の割合が高く、かつ non-child の割合も高い場合、そのノード自体がボトルネックであることを示します (子オペレーターではありません)。最適化の取り組みをそのノードに集中させてください。
クエリプロファイルのエクスポート
クエリプロファイルのエクスポートには、SelectDB Core V3.0.4 以降が必要です。
オフラインでの分析や共有のために、プロファイルをファイルにエクスポートします。
クエリプロファイルを有効化します。
SET enable_profile=true;プロファイルを取得したいクエリを実行します。
-- 対象のクエリを実行します。SelectDB はそのプロファイルを生成します。 SELECT count(1) FROM test_table LIMIT 10;プロファイル ID を取得します。
SelectDB 4.0.x バージョン
HTTP リクエストを送信してクエリ情報を取得します。応答の
Query IDフィールドがプロファイル ID です。curl -u'<userName>:<userPassword>' \ "http://<selectdbAddress>:<httpPort>/rest/v2/manager/query/query_info?is_all_node=true"応答例:
{ "msg": "success", "code": 0, "data": { "column_names": [ "Query ID", "FE Node", "Query User", "Execution Database", "Sql", "Query Type", "Start Time", "End Time", "Execution Duration", "Status" ], "rows": [ [ ... ] ] }, "count": 0 }SelectDB 3.0.x バージョン
次の例は、SelectDB 3.0 を取得する方法を示しています。
SHOW QUERY PROFILE "/";出力例:
+-----------------------------------+-----------+---------------------+---------------------+-------+------------+-------+------------------------------------+-------------------------------+ | Profile ID | Task Type | Start Time | End Time | Total | Task State | User | Default Db | Sql Statement | +-----------------------------------+-----------+---------------------+---------------------+-------+------------+-------+------------------------------------+-------------------------------+ | b9c9ba063d9d4365-97878361371e757a | QUERY | 2024-02-07 17:40:04 | 2024-02-07 17:40:04 | 32ms | EOF | admin | default_cluster:information_schema | select * from user_privileges | | 8800c306137e4072-9bb1ed419f4ac9f2 | QUERY | 2024-02-07 17:40:00 | 2024-02-07 17:40:00 | 3ms | ERR | admin | default_cluster:information_schema | select * from user_priveleges | | e2efdd1a996c4de2-ab939ad49b409990 | QUERY | 2024-02-07 17:39:51 | 2024-02-07 17:39:51 | 13ms | EOF | admin | | SELECT DATABASE() | +-----------------------------------+-----------+---------------------+---------------------+-------+------------+-------+------------------------------------+-------------------------------+プロファイル ID を使用してプロファイルをエクスポートします。
プレースホルダー 説明 デフォルト <userName>SelectDB インスタンスにアクセスするためのユーザー名 — <userPassword>SelectDB インスタンスにアクセスするためのパスワード — <selectdbAddress>SelectDB インスタンスのエンドポイント — <httpPort>HTTP ポート番号 8080 <query_id>ステップ 3 で取得したプロファイル ID — curl -u'<userName>:<userPassword>' \ "http://<selectdbAddress>:<httpPort>/api/profile?query_id=<query_id>"出力をファイルに保存するには、応答をリダイレクトします。
curl -u'<userName>:<userPassword>' \ "http://<selectdbAddress>:<httpPort>/api/profile?query_id=<query_id>" > res.txt次のプレースホルダーを実際の値に置き換えてください。
(オプション) エクスポートされたファイルを読みやすくフォーマットします。
sudo sed -r 's/\\n/\n/g' res.txt | sed -r 's/\\t/\t/g' > new.txt
プロファイルパラメーターのリファレンス
以下の表は、クエリプロファイルで収集されるすべてのパラメーターを説明しています。
フラグメント
| パラメーター | 説明 |
|---|---|
AverageThreadTokens | フラグメントの実行に使用されるスレッド数 (スレッドプールの使用を除く)。 |
Buffer Pool PeakReservation | バッファープールのピークメモリ使用量。 |
MemoryLimit | クエリのメモリ制限。 |
PeakMemoryUsage | クエリ中の実行ユニットのピークメモリ使用量。 |
RowsProduced | 列が処理された行数。 |
BlockMgr
| パラメーター | 説明 |
|---|---|
BlocksCreated | BlockManager によって作成されたブロック数。 |
BlocksRecycled | 再利用されたブロック数。 |
BytesWritten | ディスクに書き込まれたデータの合計サイズ。 |
MaxBlockSize | 単一ブロックのサイズ。 |
TotalReadBlockTime | ブロックの読み取りに消費された合計時間。 |
DataStreamSender
| パラメーター | 説明 |
|---|---|
BytesSent | 送信されたデータの合計サイズ。計算式:受信者数 x 送信データサイズ。 |
IgnoreRows | フィルターで除外された行数。 |
LocalBytesSent | データ交換中にローカルノードによって送信され、ローカルノードによって受信されたデータのサイズ。 |
OverallThroughput | 合計スループット。計算式:BytesSent / 実行時間。 |
SerializeBatchTime | 送信データのシリアル化に消費された時間。 |
UncompressedRowBatchSize | 圧縮前の送信 RowBatch データのサイズ。 |
ODBC_TABLE_SINK
| パラメーター | 説明 |
|---|---|
NumSentRows | 外部テーブルに書き込まれた行の総数。 |
TupleConvertTime | 送信データを INSERT 文にシリアル化するために消費された時間。 |
ResultSendTime | オープンデータベースコネクティビティ (ODBC) ドライバーを使用してデータを書き込むために消費された時間。 |
EXCHANGE_NODE
| パラメーター | 説明 |
|---|---|
BytesReceived | ネットワーク経由で受信したデータのサイズ。 |
MergeGetNext | 子ノードでソートが実行される場合、exchange ノードは統合されたマージとソートを実行します。これは、MergeGetNextBatch を含む、そのマージとソートの合計時間です。 |
MergeGetNextBatch | マージノードがデータをフェッチするために消費した時間。単一レベルのマージとソートの場合、データはネットワークキューからフェッチされます。複数レベルのマージとソートの場合、データは子マージャーからフェッチされます。 |
ChildMergeGetNext | 多くの送信者がデータを送信している場合、シングルスレッドのマージがボトルネックになります。ApsaraDB for SelectDB は、子マージノードで複数のスレッドを起動して、並行してマージとソートを行います。これは、すべてのスレッドにわたる累積時間です。 |
ChildMergeGetNextBatch | 子マージノードがデータをフェッチするために消費した時間。値が高い場合は、子データ送信ノードにボトルネックがある可能性があります。 |
DataArrivalWaitTime | 送信者がデータを送信するのを待機した合計時間。 |
FirstBatchArrivalWaitTime | 送信者からの最初のデータバッチを待機する時間。 |
DeserializeRowBatchTimer | ネットワークデータの逆シリアル化に消費された時間。 |
SendersBlockedTotalTimer(*) | DataStreamRecv キューのメモリが完全に占有された場合の送信者側の合計待機時間。 |
ConvertRowBatchTime | 受信データを RowBatch に変換するために消費された時間。 |
RowsReturned | 受信した行数。 |
RowsReturnedRate | 行が受信されるレート。 |
SORT_NODE
| パラメーター | 説明 |
|---|---|
InMemorySortTime | インメモリソートに消費された時間。 |
InitialRunsCreated | ソートが初期化された回数。インメモリソートの場合、値は 1 です。 |
SortDataSize | ソートされたデータの合計サイズ。 |
MergeGetNext | MergeSort が複数のソート済みランから次のバッチを取得するために消費した時間。データがディスクに書き込まれた場合にのみ測定されます。 |
MergeGetNextBatch | MergeSort が次のソート済みランのバッチを抽出するために消費した時間。データがディスクに書き込まれた場合にのみ測定されます。 |
TotalMergesPerformed | 外部マージが実行された回数。 |
AGGREGATION_NODE
| パラメーター | 説明 |
|---|---|
PartitionsCreated | 集計クエリが分割されるパーティションの数。 |
GetResultsTime | パーティションから集計結果を取得するために消費された時間。 |
HTResizeTime | ハッシュテーブルのサイズ変更に消費された時間。 |
HTResize | ハッシュテーブルがサイズ変更された回数。 |
HashBuckets | ハッシュテーブル内のバケット数。 |
HashBucketsWithDuplicate | ハッシュテーブル内の重複ノードを持つバケット数。 |
HashCollisions | ハッシュテーブル内のハッシュ衝突の数。 |
HashDuplicateNodes | ハッシュテーブル内の同じバケットに属する重複ノードの数。 |
HashFailedProbe | ハッシュテーブルでのプローブ操作の失敗回数。 |
HashFilledBuckets | ハッシュテーブル内でデータが埋められたバケット数。 |
HashProbe | ハッシュテーブルがクエリされた回数。 |
HashTravelLength | ハッシュテーブルクエリ中に移動したステップ数。 |
HASH_JOIN_NODE
| パラメーター | 説明 |
|---|---|
ExecOption | 右子ノードのハッシュテーブル構築メソッド:同期または非同期。 |
BuildBuckets | ハッシュテーブル内のバケット数。 |
BuildRows | ハッシュテーブル内の行数。 |
BuildTime | ハッシュテーブルの構築に消費された時間。 |
LoadFactor | ハッシュテーブルのロードファクター。空でないバケットの数を示します。 |
ProbeRows | 左子ノードを走査した後にハッシュプローブ操作が実行された行数。 |
ProbeTime | 左子ノードから RowBatch の GetNext を呼び出す時間を除き、ハッシュプローブのために左子ノードを走査するのに消費された時間。 |
PushDownComputeTime | 述語プッシュダウン条件の計算に消費された時間。 |
PushDownTime | 述語プッシュダウンに消費された合計時間。条件を満たす右子ノードでの Join クエリは、左子ノードでの IN クエリに変換されます。 |
CROSS_JOIN_NODE
| パラメーター | 説明 |
|---|---|
ExecOption | 右子ノードの RowBatchList 構築メソッド:同期または非同期。 |
BuildRows | RowBatchList の行数 (右子ノードの行数)。 |
BuildTime | RowBatchList の構築に消費された時間。 |
LeftChildRows | 左子ノードの行数。 |
LeftChildTime | 左子ノードから RowBatch の GetNext を呼び出す時間を除き、デカルト積を生成するために左右の子ノードを走査するのに消費された時間。 |
UNION_NODE
| パラメーター | 説明 |
|---|---|
MaterializeExprsEvaluateTime | UNION の両側でフィールドタイプが異なる場合に、型変換式を評価し、結果をマテリアライズするために消費された時間。 |
ANALYTIC_EVAL_NODE
| パラメーター | 説明 |
|---|---|
EvaluationTime | 分析関数 (ウィンドウ関数) の計算に消費された合計時間。 |
GetNewBlockTime | 初期化中に新しいブロックを割り当てるために消費された時間。ブロックは、分析関数の計算のために Rows ウィンドウまたはパーティション全体をキャッシュします。 |
PinTime | 新しいブロックを割り当てるか、ディスクに書き込まれたブロックをメモリに再読み込みするために消費された時間。 |
UnpinTime | ブロックが不要になったとき、または現在のオペレーターが高いメモリプレッシャー下にあるときに、ブロックのデータをディスクに書き込むために消費された時間。 |
OLAP_SCAN_NODE
OLAP_SCAN_NODE はデータスキャンタスクを処理します。1 つ以上の OLAP スキャナーを作成し、それぞれがデータの一部をスキャンする責任を負います。プロファイルは、呼び出し階層を反映する 3 つのレイヤーで構成されています:OLAP_SCAN_NODE -> OlapScanner -> SegmentIterator。
述語条件の一部またはすべてが OLAP_SCAN_NODE にプッシュされます。ストレージエンジンのインデックスを使用できる条件は、さらにストレージエンジンにプッシュされてフィルタリングされます。残りは OLAP_SCAN_NODE 自体で評価されます。
次の例は、典型的な OLAP_SCAN_NODE プロファイルを示しています。
OLAP_SCAN_NODE (id=0):(Active: 1.2ms, % non-child: 0.00%)
- BytesRead: 265.00 B # データファイルから読み取られたデータのサイズ。例:10 x 32 ビット整数 = 40 バイト。これは生の I/O サイズではなく、完全にメモリにロードされたデータを反映します。
- NumDiskAccess: 1 # ScanNode がアクセスしたディスクの数。
- NumScanners: 20 # ScanNode によって作成されたスキャナーの数。
- PeakMemoryUsage: 0.00 # クエリ中のピークメモリ使用量。
- RowsRead: 7 # スキャナーによってフィルタリングされた行を除き、ストレージエンジンからスキャナーに返された行。
- RowsReturned: 7 # ScanNode から親ノードに返された行。
- RowsReturnedRate: 6.979K /sec # RowsReturned / ActiveTime。
- TabletCount: 20 # ScanNode がアクセスしたタブレットの数。
- TotalReadThroughput: 74.70 KB/sec # BytesRead を総実行時間で割った値。I/O バウンドのクエリでは、これは合計ディスクスループットに近づきます。
- ScannerBatchWaitTime: 426.886us # 転送スレッドがスキャナースレッドが RowBatch データを返すのを待つ時間。
- ScannerWorkerWaitTime: 17.745us # スキャナースレッドがスレッドプール内の利用可能なワーカースレッドを待つ時間。
OlapScanner:
- BlockConvertTime: 8.941us # ベクトル化されたブロックを行構造の RowBlock に変換する時間。ベクトル化されたブロックは VectorizedRowBatch (V1) または RowBlockV2 (V2) です。
- BlockFetchTime: 468.974us # rowset リーダーがブロックを取得する時間。
- ReaderInitTime: 5.475ms # OLAP スキャナーがリーダーを初期化する時間。MergeHeap の作成時間 (V1) と、すべてのイテレーターレベルを生成して最初のブロックグループを読み取る時間 (V2) を含みます。
- RowsDelFiltered: 0 # タブレットの DELETE 情報に基づいてフィルタリングされた行と、Unique Key モデルで削除マークが付けられた行。
- RowsPushedCondFiltered: 0 # Join 操作からプッシュダウンされた述語によってフィルタリングされた行 (例:BuildTable から ProbeTable へ)。この値は近似値です。効果が低い場合、フィルタリングがスキップされることがあります。
- ScanTime: 39.24us # データが ScanNode から親ノードに移動する時間。
- ShowHintsTime_V1: 0ns # V1 のみ:ScanRange 分割のために一部のデータを読み取る時間。
SegmentIterator:
- BitmapIndexFilterTimer: 779ns # ビットマップインデックスを使用してデータをフィルタリングする時間。
- BlockLoadTime: 415.925us # セグメントリーダー (V1) またはセグメントイテレーター (V2) がブロックを取得する時間。
- BlockSeekCount: 12 # セグメント読み取り中のブロックシーク数。
- BlockSeekTime: 222.556us # セグメント読み取り中のブロックシークに消費された時間。
- BlocksLoad: 6 # 読み取られたブロックの数。
- CachedPagesNum: 30 # V2 のみ:ページキャッシュにヒットしたページ数。
- CompressedBytesRead: 0.00 # V1:ファイルから読み取られた展開前のデータのサイズ。V2:ページキャッシュにヒットしなかったページの圧縮前のサイズ。
- DecompressorTimer: 0ns # データ展開に消費された時間。
- IOTimer: 0ns # オペレーティングシステムからデータを読み取るための実際の I/O 時間。
- IndexLoadTime_V1: 0ns # V1 のみ:インデックスストリームを読み取る時間。
- NumSegmentFiltered: 0 # 列統計情報とクエリ条件に基づいて完全にフィルタリングされたセグメントの数。
- NumSegmentTotal: 6 # クエリに関与したセグメントの総数。
- RawRowsRead: 7 # 先行するすべてのフィルタリングの後、ストレージエンジンから読み取られたソースデータ行。
- RowsBitmapIndexFiltered: 0 # V2 のみ:ビットマップインデックスを使用してフィルタリングされた行。
- RowsBloomFilterFiltered: 0 # V2 のみ:BloomFilter インデックスを使用してフィルタリングされた行。
- RowsKeyRangeFiltered: 0 # V2 のみ:SortkeyIndex インデックスを使用してフィルタリングされた行。
- RowsStatsFiltered: 0 # V2:ZoneMap インデックスを使用してフィルタリングされた行 (削除条件を含む)。V1:BloomFilter インデックスを使用してフィルタリングされた行を含む。
- RowsConditionsFiltered: 0 # V2 のみ:すべての列インデックスを組み合わせてフィルタリングされた行。
- RowsVectorPredFiltered: 0 # ベクトル化された条件操作によってフィルタリングされた行。
- TotalPagesNum: 30 # V2 のみ:読み取られたページの総数。
- UncompressedBytesRead: 0.00 # V1:展開後のデータのサイズ (または圧縮されていない場合はファイルサイズ)。V2:ページキャッシュにヒットしなかったページの展開後のサイズ (または圧縮されていない場合はページサイズ)。
- VectorPredEvalTime: 0ns # ベクトル化された条件によるフィルタリングを実行する時間。
- ShortPredEvalTime: 0ns # 短絡評価述語によるフィルタリングを実行する時間。
- PredColumnReadTime: 0ns # 述語列の読み取りに消費された時間。
- LazyReadTime: 0ns # 非述語列の読み取りに消費された時間。
- OutputColumnTime: 0ns # 列のマテリアライズに消費された時間。フィルタリングメトリクスの相互関係
OLAP_SCAN_NODE プロファイルの行数メトリクスは、各段階で述語とインデックスがデータ量をどれだけ効果的に削減したかを示します。以下では、V2 フォーマットのフィルタリングシーケンスについて説明します。V1 フォーマットのメトリクスは意味が若干異なります。
初期化フェーズ
フィルタリングは次の順序で行われます。
SortkeyIndex — クエリにキー範囲 (プレフィックスキー範囲) がある場合、データは最初にフィルタリングされます。除外された行は
RowsKeyRangeFilteredに記録されます。ビットマップインデックス — ビットマップインデックスに一致する条件に対して、正確な列フィルタリングが適用されます。除外された行は
RowsBitmapIndexFilteredに記録されます。BloomFilter インデックス — 等価条件 (
=、IN、IS) は BloomFilter インデックスを使用してフィルタリングされます。除外された行はRowsBloomFilterFilteredに記録されます。説明RowsBloomFilterFilteredは、セグメントの総行数から BloomFilter フィルタリング後の残りの行数を引いて計算されます。ビットマップインデックスによって既に除外された行と重複する可能性があります。ZoneMap インデックス — データはクエリ条件と削除条件に基づいてフィルタリングされます。除外された行は
RowsStatsFilteredに記録されます。RowsConditionsFilteredは、RowsBloomFilterFilteredとRowsStatsFilteredを含む、すべてのインデックスを組み合わせてフィルタリングされた合計行数です。
次のフェーズ
初期化後、残りのデータは追加のステージを通過します。
RowsDelFiltered:削除条件によって除外された行。これらはRowsStatsFilteredにもカウントされます。RawRowsRead:先行するすべてのフィルタリング後に残った行。RowsRead:ストレージエンジンからスキャナーに返された行。ストレージエンジンが行を集約する場合があるため、これは通常RawRowsReadよりも少なくなります。RawRowsReadとRowsReadの間に大きなギャップがある場合は、集約が多発していることを示し、パフォーマンス上の懸念となる可能性があります。RowsReturned:最終的に ScanNode から親ノードに返された行。ストレージエンジンにプッシュされなかった述語がスキャナーレベルで適用されるため、これは通常RowsReadよりも少なくなります。RowsReadとRowsReturnedの間に大きなギャップがある場合は、多くの高選択性述語が、より効率的なフィルタリングが行われるストレージエンジンに到達していないことを意味します。
まとめると、Rows***Filtered メトリクスにより、クエリ述語がストレージエンジンにプッシュされているかどうか、また各インデックスタイプがどれほど効果的かを評価できます。
その他のメトリクス
OlapScanner配下のメトリクス (例:IOTimerやBlockFetchTime) は、すべてのスキャナースレッドにわたる累積値です。スキャナースレッドは非同期でデータを読み取るため、これらの累積値は ScanNode のウォールクロック時間ではなく、スキャナーの総作業時間を反映します。Activeの割合は、ScanNode が全体の実行計画に実際に貢献した時間の割合を記録します。IOTimerが数十秒であるのに対し、Activeがわずか数秒であるのは正常です。これには 2 つの理由があります。IOTimerは並行して実行される多くのスキャナーにわたって累積されます。親ノードが遅い場合 (例:100 秒)、ScanNode (10 秒) は早期に終了し、バックグラウンドでデータを準備します。その後、親ノードが準備されたデータを取得するため、ScanNode の
Active時間は短くなります。
NumScannersは、スキャナーがスレッドプールにサブミットするタスクの数であり、これはRuntimeStateによって管理されます。doris_scanner_thread_pool_thread_numとdoris_scanner_thread_pool_queue_sizeパラメーターは、スレッドプールのサイズとキューの長さを制御します。スレッド数が過剰または不足している場合、クエリ効率に影響します。また、一部のメトリクスをスレッド数で割ることで、各スレッドが消費した時間をおおよそ見積もることができます。TabletCountはスキャンするタブレットの数です。タブレット数が多いと、ランダムリードやデータマージ操作が増加します。UncompressedBytesReadは読み取られたデータ量を反映します。値が高い場合は、I/O が重いことを示している可能性があります。CachedPagesNumとTotalPagesNumを比較して、ページキャッシュのヒット率を評価します。ヒット率が高いほど、I/O と展開の両方のオーバーヘッドが削減されます。
バッファープール
| パラメーター | 説明 |
|---|---|
AllocTime | メモリ割り当てに消費された時間。 |
CumulativeAllocationBytes | 割り当てられたメモリの累積サイズ。 |
CumulativeAllocations | メモリ割り当ての累積回数。 |
PeakReservation | ピーク予約サイズ。 |
PeakUnpinnedBytes | アンピンされたメモリデータのサイズ。 |
PeakUsedReservation | 予約のメモリ使用量。 |
ReservationLimit | バッファープール内の予約制限。 |