メインコンテンツまでスキップ
バージョン: 2.1

Statistics

バージョン2.0以降、DorisはオプティマイザーにCost-Based 最適化(CBO)機能を統合しました。統計情報はCBOの基盤であり、その精度はコスト推定の精度を直接決定し、最適な実行プランの選択にとって重要です。このドキュメントは、未リリースの開発バージョンにおける統計情報の使用ガイドとして機能し、収集と管理方法、関連する設定オプション、よくある質問に焦点を当てています。

統計情報の収集

Dorisはデフォルトで内部Tableの自動サンプリング収集を有効にしています。したがって、ほとんどの場合、ユーザーは統計情報の収集に注意を払う必要がありません。Dorisは各Tableに対してカラムレベルで統計情報を収集します。収集される情報には以下が含まれます:

Info of Statisticsデスクリプション
row_count総行数
data_sizeカラムの総データサイズ
avg_size_byteカラムの1行あたりの平均データサイズ
ndv異なる値の数
min最小値
max最大値
null_countnull値の数

現在、システムはBOOLEAN、TINYINT、SMALLINT、INT、BIGINT、LARGEINT、FLOAT、DOUBLE、DATE、DATETIME、STRING、VARCHAR、TEXTなど、基本データ型のカラムに対する統計情報の収集のみをサポートしています。

JSONB、VARIANT、MAP、STRUCT、ARRAY、HLL、BITMAP、TIME、TIMEV2などの複合型のカラムはスキップされます。

統計情報は手動または自動で収集でき、結果はinternal.__internal_schema.column_statisticsTableに保存されます。以下のセクションでは、これら2つの収集方法について詳しく説明します。

手動収集

DorisはユーザーがANALYZE文を実行することで、統計情報の収集と更新を手動でトリガーすることを可能にします。

1. 構文

ANALYZE < TABLE table_name > | < DATABASE db_name > 
[ (column_name [, ...]) ]
[ [ WITH SYNC ] [ WITH SAMPLE PERCENT | ROWS ] ];

パラメータの説明:

  • table_name: 統計情報を収集する対象Tableを指定します。

  • column_name: 統計情報を収集する対象カラムを指定します。これらのカラムはtable_nameに存在する必要があり、複数のカラム名はカンマで区切ります。カラム名が指定されない場合、Table内のすべてのカラムについて統計情報が収集されます。

  • sync: 統計情報を同期的に収集するためのオプションパラメータです。指定された場合、収集完了後に結果が返されます。指定されない場合、操作は非同期で実行され、JOB IDが返されます。このIDは収集タスクのステータスを確認するために使用できます。

  • sample percent | rows: 統計情報収集時のサンプリングのためのオプションパラメータです。サンプリング率または行数を指定できます。WITH SAMPLEが指定されない場合、フルTableスキャンが実行されます。大きなTable(例:5 GiBを超える)の場合、クラスターリソース使用率の観点から、一般的にサンプリングが推奨されます。統計情報の精度を確保するため、少なくとも400万行をサンプリングすることが推奨されます。

2. 例

lineitemTableのすべてのカラムについて統計情報を収集する:

ANALYZE TABLE lineitem;

tpch100データベース内のすべてのTableのすべての列について統計情報を収集します:

ANALYZE DATABASE tpch100;

lineitemTableのl_orderkeyl_linenumber列の統計情報を100,000行をサンプリングして収集します(注意:正しい構文はWITH SAMPLE ROWSまたはWITH SAMPLE PERCENTを使用してください):

ANALYZE TABLE lineitem WITH SAMPLE ROWS 100000;

Automatic Collection

自動収集はバージョン2.0.3以降でサポートされており、一日を通してデフォルトで有効になっています。ユーザーはENABLE_AUTO_ANALYZE変数を設定することで、この機能の有効化または無効化を制御できます:

SET GLOBAL ENABLE_AUTO_ANALYZE = TRUE; // Enable automatic collection  
SET GLOBAL ENABLE_AUTO_ANALYZE = FALSE; // Disable automatic collection

有効にすると、バックグラウンドスレッドがクラスター内のInternalCatalog内のすべてのTableを定期的にスキャンします。統計収集が必要なTableに対して、システムは手動介入なしで自動的に収集ジョブを作成して実行します。

広範囲のTableの統計収集による過度なリソース使用を避けるため、300列を超えるTableはデフォルトでは自動的に収集されません。ユーザーはセッション変数auto_analyze_table_width_thresholdを変更することで、この閾値を調整できます:

SET GLOBAL auto_analyze_table_width_threshold = 350;

自動収集のデフォルトポーリング間隔は5分です(fe.confauto_check_statistics_in_minutes設定で調整可能)。最初の反復はクラスター起動から5分後に開始されます。収集が必要なすべてのTableの処理が完了すると、バックグラウンドスレッドは5分間スリープしてから次の反復を開始します。したがって、すべてのTableを反復処理する時間はTableの数とサイズによって変動するため、Tableの統計が5分以内に収集される保証はありません。

Tableがポーリングされると、システムはまず統計収集が必要かどうかを判断します。必要な場合は収集ジョブが作成され実行されます。そうでなければ、そのTableはスキップされます。統計収集が必要な条件は以下の通りです:

  1. Tableに統計のない列がある。

  2. Tableのヘルスがしきい値を下回っている(デフォルト90、table_stats_health_thresholdで調整可能)。ヘルスは前回の統計収集以降に変更されていないデータの割合を示します:100は変更なし、0はすべて変更、90を下回るヘルスは現在の統計に大きな偏差があることを示し、再収集が必要です。

バックグラウンドジョブのオーバーヘッドを削減し収集速度を向上させるため、自動収集はデフォルトでサンプリングを使用し、4,194,304(2^22)行をサンプリングします。ユーザーはhuge_table_default_sample_rowsを変更してサンプリングサイズを調整し、より正確なデータ分散情報を得ることができます。

自動収集ジョブがビジネス運用に干渉することを防ぐため、ユーザーはauto_analyze_start_timeauto_analyze_end_timeを設定することで、要件に基づいて自動収集の実行ウィンドウを指定できます:

SET GLOBAL auto_analyze_start_time = "03:00:00"; // Set the start time to 3 AM  
SET GLOBAL auto_analyze_end_time = "14:00:00"; // Set the end time to 2 PM

External Table Collection

外部Tableには通常、Hive、Iceberg、JDBC、およびその他のタイプが含まれます。

  • Manual Collection: Hive、Iceberg、およびJDBCTableはマニュアル統計収集をサポートします。HiveTableはフル収集とサンプル収集の両方をサポートしますが、IcebergおよびJDBCTableはフル収集のみをサポートします。その他の外部Tableタイプはマニュアル収集をサポートしません。

  • Automatic Collection: 現在、HiveTableのみがサポートされています。

外部カタログは、大量の履歴データを含むことが多く、自動収集時に過度なリソースを消費する可能性があるため、デフォルトでは自動収集に参加しません。ただし、プロパティを設定することで外部Catalogの自動収集を有効または無効にできます:

ALTER CATALOG external_catalog SET PROPERTIES ('enable.auto.analyze'='true'); // Enable automatic collection  
ALTER CATALOG external_catalog SET PROPERTIES ('enable.auto.analyze'='false'); // Disable automatic collection

外部Tableにはヘルスの概念がありません。Catalogで自動収集が有効化されている場合、システムは頻繁な収集を避けるため、外部Tableに対して24時間ごとに1回のみ統計情報を収集することをデフォルトとしています。外部Tableの最小収集間隔はexternal_table_auto_analyze_interval_in_millis変数を使用して調整できます。

デフォルトでは、外部Tableは統計情報を収集しませんが、HiveおよびIcebergTableに対しては、システムはHive MetastoreおよびIceberg APIを通じて行数情報の取得を試行します。

1. HiveTableの場合:

DorisはまずHiveTableのParametersからnumRowsまたはtotalSize情報の取得を試行します:

  • numRowsが見つかった場合、その値がTableの行数として使用されます。

  • numRowsが見つからないがtotalSizeが利用可能な場合、TableのスキーマとtotalSizeに基づいて行数が推定されます。

  • totalSizeも利用できない場合、デフォルトでは、システムはHiveTableに対応するファイルサイズとそのSchemaに基づいて行数を推定します。ファイルサイズの取得が過剰なリソースを消費する可能性に懸念がある場合、以下の変数を設定してこの機能を無効化できます。

    SET GLOBAL enable_get_row_count_from_file_list = FALSE

2. IcebergTableの場合:

DorisはIcebergスナップショットAPIを呼び出してtotal-recordstotal-position-deletesの情報を取得し、Tableの行数を計算します。

3. PaimonTableの場合:

DorisはPaimonのscan APIを呼び出して各Splitに含まれる行数を取得し、Splitの行数を合計してTableの行数を計算します。

4. JDBCTableの場合:

DorisはTable統計を読み取るSQLをリモートデータベースに送信して、Tableの行数を取得します。これは、リモートデータベースがTableの行数情報を収集している場合にのみ実現できます。現在、DorisはMySQL、Oracle、PostgreSQL、SQLServerのTableの行数取得をサポートしています。

5. その他の外部Tableの場合:

自動的な行数取得と推定は現在サポートされていません。

ユーザーは以下のコマンドを使用して外部Tableの推定行数を確認できます(詳細はViewing Table Statistics 概要を参照してください):

SHOW table stats table_name;
  • row_count-1と表示される場合、行数情報を取得できなかったか、Tableが空です。

Statistics Job Management

統計ジョブの表示

統計収集ジョブの情報を表示するにはSHOW ANALYZEを使用します。現在、システムは20,000件の履歴ジョブの情報のみを保持します。このコマンドを使用して表示できるのは非同期ジョブの情報のみであることに注意してください。同期ジョブ(WITH SYNCを使用)は履歴ジョブ情報を保持しません。

1. 構文:

SHOW [AUTO] ANALYZE < table_name | job_id >
[ WHERE STATE = < "PENDING" | "RUNNING" | "FINISHED" | "FAILED" > ];
  • AUTO: 履歴の自動収集ジョブに関する情報を表示します。未指定の場合、手動の ANALYZE 履歴ジョブに関する情報を表示します。

  • table_name: Table名。指定すると、そのTableの統計ジョブ情報を表示できます。db_name.table_name の形式で指定できます。未指定の場合、すべての統計ジョブに関する情報を返します。

  • job_id: 統計ジョブID。非同期 ANALYZE 収集の実行時に取得されます。未指定の場合、コマンドはすべての統計ジョブに関する情報を返します。

2. 出力:

以下のカラムが含まれます:

カラム名説明
job_id統計ジョブID
catalog_nameカタログ名
db_nameデータベース名
tbl_nameTable名
col_nameカラム名のリスト (index_name:column_name)
job_typeジョブタイプ
analysis_type統計タイプ
messageジョブ情報
stateジョブ状態
progressジョブ進捗
schedule_typeスケジューリングタイプ
start_timeジョブ開始時刻
end_timeジョブ終了時刻

3. 例:

mysql show analyze 245073\G;
*************************** 1. row ***************************
job_id: 93021
catalog_name: internal
db_name: tpch
tbl_name: region
col_name: [region:r_regionkey,region:r_comment,region:r_name]
job_type: MANUAL
analysis_type: FUNDAMENTALS
message:
state: FINISHED
progress: 3 Finished | 0 Failed | 0 In Progress | 3 Total
schedule_type: ONCE
start_time: 2024-07-11 15:15:00
end_time: 2024-07-11 15:15:33

統計情報タスクの表示

各収集ジョブには1つ以上のタスクを含めることができ、各タスクは単一列の収集に対応します。ユーザーは以下のコマンドを使用して、各列の統計情報収集の完了状況を表示できます。

1. 構文:

SHOW ANALYZE TASK STATUS [job_id]

2. 例:

mysql> show analyze task status 93021;
+---------+-------------+------------+---------+------------------------+-----------------+----------+
| task_id | col_name | index_name | message | last_state_change_time | time_cost_in_ms | state |
+---------+-------------+------------+---------+------------------------+-----------------+----------+
| 93022 | r_regionkey | region | | 2024-07-11 15:15:33 | 32883 | FINISHED |
| 93023 | r_comment | region | | 2024-07-11 15:15:33 | 32883 | FINISHED |
| 93024 | r_name | region | | 2024-07-11 15:15:33 | 32883 | FINISHED |
+---------+-------------+------------+---------+------------------------+-----------------+----------+

統計情報の表示

ユーザーはSHOW COLUMN STATSコマンドを使用して、収集された列統計情報を表示することができます。

1. 構文:

SHOW COLUMN [cached] STATS table_name [ (column_name [, ...]) ];

ここで:

  • cached: FE メモリ内に現在キャッシュされている統計情報を表示します。

  • table_name: 統計情報が収集された対象Table。db_name.table_name の形式で指定できます。

  • column_name: 指定された対象カラム。table_name に存在する必要があり、複数のカラム名はカンマで区切ります。指定されていない場合、すべてのカラムの情報を表示します。

2. 例:

mysql> show column stats region (r_regionkey)\G
*************************** 1. row ***************************
column_name: r_regionkey
index_name: region
count: 5.0
ndv: 5.0
num_null: 0.0
data_size: 20.0
avg_size_byte: 4.0
min: 0
max: 4
method: FULL
type: FUNDAMENTALS
trigger: MANUAL
query_times: 0
updated_time: 2024-07-11 15:15:33
1 row in set (0.36 sec)

Table統計の概要の表示

SHOW TABLE STATSを使用して、Table統計収集の概要を表示します。

1. 構文:

SHOW TABLE STATS table_name;

Where: table_name: 対象Table名。db_name.table_nameの形式で指定可能。

2. 出力:

以下のカラムが含まれます:

Column Nameデスクリプション
updated_rows前回のANALYZE以降にTableで更新された行数
query_times予約カラム。将来のバージョンでTableへのクエリ回数を記録するため
row_countTable内の行数(コマンド実行時の正確な数を反映しない場合があります)
updated_time統計の最終更新時刻
columns統計が収集されたカラム
trigger統計がトリガーされた方法
new_partition初回データインポートを伴う新しいパーティションがあるかどうか
user_injectユーザーによって統計が手動で注入されたかどうか

3. 例:

mysql> show column stats region (r_regionkey)\G
*************************** 1. row ***************************
column_name: r_regionkey
index_name: region
count: 5.0
ndv: 5.0
num_null: 0.0
data_size: 20.0
avg_size_byte: 4.0
min: 0
max: 4
method: FULL
type: FUNDAMENTALS
trigger: MANUAL
query_times: 0
updated_time: 2024-07-11 15:15:33
1 row in set (0.36 sec)

Statistics Jobs の停止

現在実行中の非同期statistics jobを終了するには、KILL ANALYZEを使用します。

1. 構文:

KILL ANALYZE job_id;

Where: job_id: 統計ジョブのID。これはANALYZEで非同期統計収集を実行した際に返される値、またはSHOW ANALYZE文を使用して取得される値です。

2. 例:

ID 52357の統計ジョブを終了します。

mysql> KILL ANALYZE 52357;

統計情報の削除

カタログ、Database、またはTableが削除された場合、ユーザーはその統計情報を手動で削除する必要はありません。バックグラウンドプロセスが定期的にこの情報をクリーンアップします。

ただし、まだ存在するTableについては、システムはそれらの統計情報を自動的にクリアしません。この場合、ユーザーは以下の構文を使用して手動で削除する必要があります:

DROP STATS table_name

セッション変数と設定オプション

セッション変数

セッション変数説明デフォルト値
auto_analyze_start_time自動統計収集の開始時刻0:00:00
auto_analyze_end_time自動統計収集の終了時刻23:59:59
enable_auto_analyze自動収集機能を有効にするかどうかTRUE
huge_table_default_sample_rows大きなTableに対してサンプルする行数4194304
table_stats_health_threshold値の範囲は0-100で、最後の統計収集以降に更新されたデータの割合を示し、(100 - table_stats_health_threshold)%において統計が古いとみなされる90
auto_analyze_table_width_threshold自動統計収集の最大Table幅を制御し、この列数を超えるTableは自動統計収集に参加しない300
enable_get_row_count_from_file_listファイルサイズに基づいてHiveTableの行数を推定するかどうかFALSE (2.1.5以降はデフォルトでTRUE)

FE設定

Note

以下のFE設定オプションは通常、特別な注意を必要としません。

FE設定オプション説明デフォルト値
analyze_record_limit統計ジョブ実行記録の永続化行数を制御する20000
stats_cache_sizeFE側でキャッシュされる統計エントリ数500000
statistics_simultaneously_running_task_num同時実行可能な非同期統計ジョブ数3
statistics_sql_mem_limit_in_bytes各統計SQLが占有できるBEメモリ量を制御する2L * 1024 * 1024 (2GiB)

FAQ

Q1: Tableの統計が収集されているかどうか、および内容が正しいかどうかを確認するにはどうすればよいですか?

まず、show column stats table_nameを実行して統計出力があるかどうかを確認します。

次に、show column cached stats table_nameを実行してTableの統計がキャッシュに読み込まれているかどうかを確認します。

mysql> show column stats test_table\G
Empty set (0.02 sec)

mysql> show column cached stats test_table\G
Empty set (0.00 sec)

空の結果は、現在test_tableに対する統計情報が存在しないことを示しています。統計情報が存在する場合、結果は以下のようになります:

mysql> show column cached stats mvTestDup;
+-------------+------------+-------+------+----------+-----------+---------------+------+------+--------+--------------+---------+-------------+---------------------+
| column_name | index_name | count | ndv | num_null | data_size | avg_size_byte | min | max | method | type | trigger | query_times | updated_time |
+-------------+------------+-------+------+----------+-----------+---------------+------+------+--------+--------------+---------+-------------+---------------------+
| key1 | mvTestDup | 6.0 | 4.0 | 0.0 | 48.0 | 8.0 | 1 | 1001 | FULL | FUNDAMENTALS | MANUAL | 0 | 2024-07-22 10:53:25 |
| key2 | mvTestDup | 6.0 | 4.0 | 0.0 | 48.0 | 8.0 | 2 | 2001 | FULL | FUNDAMENTALS | MANUAL | 0 | 2024-07-22 10:53:25 |
| value2 | mvTestDup | 6.0 | 4.0 | 0.0 | 24.0 | 4.0 | 4 | 4001 | FULL | FUNDAMENTALS | MANUAL | 0 | 2024-07-22 10:53:25 |
| value1 | mvTestDup | 6.0 | 4.0 | 0.0 | 24.0 | 4.0 | 3 | 3001 | FULL | FUNDAMENTALS | MANUAL | 0 | 2024-07-22 10:53:25 |
| mv_key1 | mv1 | 6.0 | 4.0 | 0.0 | 48.0 | 8.0 | 1 | 1001 | FULL | FUNDAMENTALS | MANUAL | 0 | 2024-07-22 10:53:25 |
| value3 | mvTestDup | 6.0 | 4.0 | 0.0 | 24.0 | 4.0 | 5 | 5001 | FULL | FUNDAMENTALS | MANUAL | 0 | 2024-07-22 10:53:25 |
+-------------+------------+-------+------+----------+-----------+---------------+------+------+--------+--------------+---------+-------------+---------------------+
6 rows in set (0.00 sec)

統計が存在する場合、SQLクエリを手動で実行してその精度を検証できます。

Select count(1), ndv(col1), min(col1), max(col1) from table

countndvのエラーが1桁程度の範囲内であれば、精度は一般的に許容範囲内です。

Q2: Tableの統計情報が自動的に収集されないのはなぜですか?

まず、自動収集が有効になっているかを確認してください:

Show variables like "enable_auto_analyze";  // If false, set it to true:  

Set global enable_auto_analyze = true

既にtrueの場合は、Tableの列数を確認してください。auto_analyze_table_width_thresholdを超えている場合、そのTableは自動収集に参加しません。この値をTableの現在の列数より大きくなるように変更してください:

Show variables like "auto_analyze_table_width_threshold"  

// If the value is less than the width of the table, you can modify it:

Set global auto_analyze_table_width_threshold=350

列数がしきい値を超えない場合は、show auto analyzeを実行して、他のコレクションタスクが実行中(running状態)かどうかを確認してください。自動コレクションは単一スレッドによってシリアルに実行されるため、すべてのデータベースとTableをポーリングするため実行サイクルが長くなる可能性があります。

Q3: 一部の列で統計情報が利用できないのはなぜですか?

現在、システムは基本データ型の列の統計情報の収集のみをサポートしています。JSONB、VARIANT、MAP、STRUCT、ARRAY、HLL、BITMAP、TIME、TIMEV2などの複合型については、システムはそれらをスキップします。

Q4: エラー: "Stats table not available, please make sure your cluster status is normal"

このエラーは通常、内部統計Tableが異常な状態にあることを示しています。

まず、クラスタ内のすべてのBE(Backend)が正常な状態にあるかを確認し、すべてが正しく機能していることを確認してください。

次に、以下のステートメントを実行して、すべてのtabletId(出力の最初の列)を取得してください:

show tablets from internal.__internal_schema.column_statistics;

その後、tablet_idを使用して各タブレットのステータスを確認します:

ADMIN DIAGNOSE TABLET tablet_id

異常なtabletが見つかった場合は、統計情報を再収集する前にまずそれらを修復してください。

Q5: 統計情報収集のタイミングが適切でない問題にどう対処すればよいですか?

自動収集の間隔は不確実で、システム内のTable数とサイズに依存します。緊急の場合は、Tableに対して手動でanalyze操作を実行してください。

大量のデータをインポートした後に自動収集がトリガーされない場合は、table_stats_health_thresholdパラメータの調整を検討してください。デフォルト値は90で、これはTableデータの10%以上(100 - 90)が変更された時に自動収集がトリガーされることを意味します。この値を例えば95に増やすことで、Tableデータの5%以上が変更された時に統計情報が再収集されるようになります。

Q6: 自動収集中の過度なリソース使用量にどう対処すればよいですか?

自動収集はサンプリングを使用し、フルTableスキャンを必要とせず、タスクは単一スレッドによってシリアルに実行されます。通常、システムリソースの使用量は管理可能で、通常のクエリタスクに影響を与えません。

多くのパーティションを持つTableや大きな個別のtabletなど、一部の特殊なTableでは、メモリ使用量が高くなる可能性があります。

Table作成時には、過大なtabletの作成を避けるため、tablet数を合理的に計画することをお勧めします。tabletの構造が調整しにくい場合は、ビジネス運用への影響を避けるため、オフピーク時間中に大きなTableの自動収集を有効にするか、手動で統計情報を収集することを検討してください。Doris 3.xシリーズでは、このようなシナリオに対する最適化を行う予定です。