統計入門

TiDB は統計を使用してどのインデックスを選択するか決定します。

統計のバージョン

tidb_analyze_version変数は、TiDB によって収集される統計を制御します。現在、 tidb_analyze_version = 1tidb_analyze_version = 2 2 つのバージョンの統計がサポートされています。

  • TiDB Self-Hosted の場合、この変数のデフォルト値は v5.3.0 以降、 1から2に変更されます。
  • TiDB Cloudの場合、この変数のデフォルト値は、v6.5.0 以降で1から2に変更されます。
  • クラスターが以前のバージョンからアップグレードされた場合、アップグレード後もデフォルト値tidb_analyze_versionは変更されません。

バージョン 1 と比較すると、バージョン 2 の統計では、データ量が非常に多い場合にハッシュ衝突によって生じる潜在的な不正確さを回避します。また、ほとんどのシナリオで推定精度を維持します。

これら 2 つのバージョンには、TiDB に異なる情報が含まれています。

情報バージョン 1バージョン2
表内の行の総数
カラム数最小スケッチ×
インデックスカウント最小スケッチ×
カラムトップN√(メンテナンス方法と精度が向上します)
インデックストップN√(メンテナンス精度が不十分だと不正確になる可能性があります)√(メンテナンス方法と精度が向上します)
カラムヒストグラム√ (ヒストグラムには Top-N 値は含まれません。)
インデックスヒストグラム√ (ヒストグラム バケットには各バケット内の異なる値の数を記録し、ヒストグラムには上位 N の値は含まれません。)
列内のNULLの数
インデックス内のNULLの数
列の平均長さ
インデックスの平均長さ

tidb_analyze_version = 2場合、 ANALYZE実行後にメモリオーバーフローが発生する場合は、 tidb_analyze_version = 1を設定してバージョン 1 にフォールバックし、次のいずれかの操作を実行する必要があります。

  • ANALYZEステートメントを手動で実行する場合は、分析対象のすべてのテーブルを手動で分析します。

    SELECT DISTINCT(CONCAT('ANALYZE TABLE ', table_schema, '.', table_name, ';')) FROM information_schema.tables, mysql.stats_histograms WHERE stats_ver = 2 AND table_id = tidb_table_id;
  • 自動分析が有効になっているため、TiDB がANALYZEステートメントを自動的に実行する場合は、 DROP STATSステートメントを生成する次のステートメントを実行します。

    SELECT DISTINCT(CONCAT('DROP STATS ', table_schema, '.', table_name, ';')) FROM information_schema.tables, mysql.stats_histograms WHERE stats_ver = 2 AND table_id = tidb_table_id;
  • 前のステートメントの結果が長すぎてコピーして貼り付けることができない場合は、結果を一時テキスト ファイルにエクスポートし、次のようにファイルから実行することができます。

    SELECT DISTINCT ... INTO OUTFILE '/tmp/sql.txt'; mysql -h ${TiDB_IP} -u user -P ${TIDB_PORT} ... < '/tmp/sql.txt'

このドキュメントでは、ヒストグラム、Count-Min Sketch、Top-N について簡単に紹介し、統計の収集と管理について詳しく説明します。

ヒストグラム

ヒストグラムは、データの分布を大まかに表したものです。値の範囲全体を一連のバケットに分割し、バケットに含まれる値の数など、単純なデータを使用して各バケットを説明します。TiDB では、各テーブルの特定の列に対して等深度ヒストグラムが作成されます。等深度ヒストグラムを使用して、間隔クエリを推定できます。

ここで「等深度」とは、各バケットに入る値の数が可能な限り等しくなることを意味します。たとえば、特定のセット {1.6、1.9、1.9、2.0、2.4、2.6、2.7、2.7、2.8、2.9、3.4、3.5} に対して、4 つのバケットを生成するとします。等深度ヒストグラムは次のようになります。[1.6、1.9][2.0、2.6][2.7、2.8][2.9、3.5] の 4 つのバケットが含まれます。バケットの深さは 3 です。

Equal-depth Histogram Example

ヒストグラムのバケット数の上限を決定するパラメータの詳細については、 手動収集を参照してください。バケット数が多いほどヒストグラムの精度は高くなりますが、精度が高くなるとメモリリソースの使用量が増大します。実際のシナリオに応じて、この数値を適切に調整できます。

カウントミニマムスケッチ

Count-Min Sketch はハッシュ構造です。等価クエリにa = 1またはINクエリ (たとえばa in (1, 2, 3) ) が含まれる場合、TiDB はこのデータ構造を使用して推定を行います。

Count-Min Sketch はハッシュ構造であるため、ハッシュ衝突が発生する可能性があります。 EXPLAIN文で、等価クエリの推定値が実際の値と大きく異なる場合、大きい値と小さい値が一緒にハッシュされていると考えられます。 この場合、ハッシュ衝突を回避するには、次のいずれかの方法を実行できます。

  • WITH NUM TOPNパラメータを変更します。TiDB は高頻度 (上位 x) データを別々に保存し、その他のデータは Count-Min Sketch に保存します。したがって、大きい値と小さい値が一緒にハッシュされるのを防ぐには、 WITH NUM TOPNの値を増やすことができます。TiDB では、デフォルト値は 20 です。最大値は 1024 です。このパラメータの詳細については、 手動収集を参照してください。
  • 2 つのパラメータWITH NUM CMSKETCH DEPTHWITH NUM CMSKETCH WIDTHを変更します。どちらもハッシュ バケットの数と衝突確率に影響します。実際のシナリオに応じて 2 つのパラメータの値を適切に増やすと、ハッシュ衝突の確率を下げることができますが、統計のメモリ使用量が高くなります。TiDB では、デフォルト値WITH NUM CMSKETCH DEPTHは 5、デフォルト値WITH NUM CMSKETCH WIDTHは 2048 です。2 つのパラメータの詳細については、 手動収集を参照してください。

上位Nの値

Top-N 値とは、列またはインデックス内で上位 N 個出現する値です。TiDB は、Top-N 値の値と出現を記録します。

統計を収集する

手動収集

現在、TiDB は完全なコレクションとして統計情報を収集します。統計を収集するには、 ANALYZE TABLEステートメントを実行できます。

注記:

  • TiDB でのANALYZE TABLEの実行時間は、MySQL や InnoDB よりも長くなります。InnoDB では少数のページのみがサンプリングされますが、TiDB では包括的な統計セットが完全に再構築されます。MySQL 用に作成されたスクリプトでは、 ANALYZE TABLE短時間の操作であると誤って想定される可能性があります。
  • v7.5.0 以降、統計の高速分析機能 ( tidb_enable_fast_analyze )増分収集機能非推奨になりました。

次の構文を使用して完全なコレクションを実行できます。

  • TableNameList内のすべてのテーブルの統計を収集するには:

    ANALYZE TABLE TableNameList [WITH NUM BUCKETS|TOPN|CMSKETCH DEPTH|CMSKETCH WIDTH]|[WITH NUM SAMPLES|WITH FLOATNUM SAMPLERATE];
  • WITH NUM BUCKETS 、生成されたヒストグラム内のバケットの最大数を指定します。

  • WITH NUM TOPN生成されるTOPNの最大数を指定します。

  • WITH NUM CMSKETCH DEPTH CM スケッチの深さを指定します。

  • WITH NUM CMSKETCH WIDTH CM スケッチの幅を指定します。

  • WITH NUM SAMPLESサンプル数を指定します。

  • WITH FLOAT_NUM SAMPLERATEサンプリング レートを指定します。

WITH NUM SAMPLESWITH FLOAT_NUM SAMPLERATEサンプルを収集する 2 つの異なるアルゴリズムに対応します。

  • WITH NUM SAMPLES 、TiDB のリザーバ サンプリング メソッドで実装されるサンプリング セットのサイズを指定します。テーブルが大きい場合、このメソッドを使用して統計を収集することはお勧めしません。リザーバ サンプリングの中間結果セットには冗長な結果が含まれるため、メモリなどのリソースに余分な負荷がかかります。
  • WITH FLOAT_NUM SAMPLERATE 、v5.3.0 で導入されたサンプリング方法です。値の範囲が(0, 1]の場合、このパラメータはサンプリング レートを指定します。これは、TiDB のベルヌーイ サンプリングの方法で実装されており、より大きなテーブルのサンプリングに適しており、収集効率とリソース使用率が向上します。

v5.3.0 より前の TiDB では、統計を収集するためにリザーバ サンプリング メソッドが使用されていました。v5.3.0 以降、TiDB バージョン 2 の統計では、デフォルトでベルヌーイ サンプリング メソッドが使用されて統計が収集されます。リザーバ サンプリング メソッドを再利用するには、 WITH NUM SAMPLESステートメントを使用できます。

現在のサンプリング レートは、適応アルゴリズムに基づいて計算されます。 SHOW STATS_METAを使用して表の行数を観察できる場合は、この行数を使用して 100,000 行に対応するサンプリング レートを計算できます。 この数を観察できない場合は、表のSHOW TABLE REGIONSの結果のAPPROXIMATE_KEYS列のすべての値の合計を別の基準として使用して、サンプリング レートを計算できます。

注記:

通常、 STATS_META APPROXIMATE_KEYSよりも信頼性が高いです。ただし、 TiDB Cloudコンソール ( サンプルデータのインポートを参照) からデータをインポートした後、 STATS_METAの結果は0なります。この状況に対処するには、 STATS_METAの結果がAPPROXIMATE_KEYSの結果よりもはるかに小さい場合に、 APPROXIMATE_KEYS使用してサンプリング レートを計算できます。

いくつかの列の統計を収集する

ほとんどの場合、SQL ステートメントを実行するときに、オプティマイザは一部の列 ( WHEREJOINORDER BY 、およびGROUP BYステートメントの列など) の統計のみを使用します。これらの列はPREDICATE COLUMNSと呼ばれます。

テーブルに多数の列がある場合、すべての列の統計を収集すると、大きなオーバーヘッドが発生する可能性があります。オーバーヘッドを削減するには、オプティマイザーが使用する特定の列またはPREDICATE COLUMNSのみの統計を収集できます。

注記:

  • 一部の列の統計の収集はtidb_analyze_version = 2にのみ適用されます。
  • TiDB v7.2.0 以降、TiDB ではtidb_analyze_skip_column_typesシステム変数が導入され、統計を収集するANALYZEコマンドを実行するときに統計収集でスキップされる列の種類を示します。システム変数はtidb_analyze_version = 2にのみ適用されます。
  • 特定の列の統計を収集するには、次の構文を使用します。

    ANALYZE TABLE TableName COLUMNS ColumnNameList [WITH NUM BUCKETS|TOPN|CMSKETCH DEPTH|CMSKETCH WIDTH]|[WITH NUM SAMPLES|WITH FLOATNUM SAMPLERATE];

    構文では、 ColumnNameListターゲット列の名前リストを指定します。複数の列を指定する必要がある場合は、カンマ,を使用して列名を区切ります。たとえば、 ANALYZE table t columns a, b 。この構文では、特定のテーブルの特定の列の統計を収集するだけでなく、インデックス付き列とそのテーブルのすべてのインデックスの統計も同時に収集します。

    注記:

    上記の構文は完全なコレクションです。たとえば、この構文を使用して列abの統計を収集した後、列cの統計も収集する場合は、追加の列cのみをANALYZE TABLE t COLUMNS cを使用して指定するのではなく、 ANALYZE table t columns a, b, cを使用して 3 つの列すべてを指定する必要があります。

  • PREDICATE COLUMNSの統計を収集するには、次の手順を実行します。

    1. TiDB がPREDICATE COLUMNSを収集できるようにするには、 tidb_enable_column_trackingシステム変数の値をONに設定します。

      設定後、TiDB は 300 秒ごとにPREDICATE COLUMNS情報をmysql.column_stats_usageシステム テーブルに書き込みます。

    2. ビジネスのクエリ パターンが比較的安定したら、次の構文を使用してPREDICATE COLUMNSの統計を収集します。

      ANALYZE TABLE TableName PREDICATE COLUMNS [WITH NUM BUCKETS|TOPN|CMSKETCH DEPTH|CMSKETCH WIDTH]|[WITH NUM SAMPLES|WITH FLOATNUM SAMPLERATE];

      この構文は、特定のテーブル内のPREDICATE COLUMNSの統計を収集するだけでなく、そのテーブル内のインデックス付き列とすべてのインデックスの統計を同時に収集します。

      注記:

      • mysql.column_stats_usageシステム テーブルにそのテーブルのPREDICATE COLUMNSレコードが含まれていない場合、上記の構文ではそのテーブル内のすべての列とすべてのインデックスの統計が収集されます。
      • この構文を使用して統計を収集した後、新しいタイプの SQL クエリを実行すると、オプティマイザーは一時的に古い列または疑似列の統計を使用し、次回から TiDB は使用された列の統計を収集します。
  • すべての列とインデックスの統計を収集するには、次の構文を使用します。

    ANALYZE TABLE TableName ALL COLUMNS [WITH NUM BUCKETS|TOPN|CMSKETCH DEPTH|CMSKETCH WIDTH]|[WITH NUM SAMPLES|WITH FLOATNUM SAMPLERATE];

ANALYZEステートメントの列構成 ( COLUMNS ColumnNameListPREDICATE COLUMNSALL COLUMNSを含む) を永続化する場合は、 tidb_persist_analyze_optionsシステム変数の値をONに設定して構成の永続性を分析する機能を有効にします。ANALYZE 構成永続化機能を有効にした後、次の操作を実行します。

  • TiDB が自動的に統計を収集する場合、または列構成を指定せずにANALYZEステートメントを実行して手動で統計を収集する場合、TiDB は統計収集に以前に保持された構成を引き続き使用します。
  • 列構成を指定してANALYZEステートメントを手動で複数回実行すると、TiDB は最新のANALYZEステートメントで指定された新しい構成を使用して、以前に記録された永続的な構成を上書きします。

統計が収集されたPREDICATE COLUMNSと列を検索するには、次の構文を使用します。

SHOW COLUMN_STATS_USAGE [ShowLikeOrWhere];

SHOW COLUMN_STATS_USAGEステートメントは次の 6 つの列を返します。

カラム名説明
Db_nameデータベース名
Table_nameテーブル名
Partition_nameパーティション名
Column_name列名
Last_used_atクエリの最適化で列統計が最後に使用された時刻
Last_analyzed_at列統計が最後に収集された時刻

次の例では、 ANALYZE TABLE t PREDICATE COLUMNS;実行した後、 TiDB は列bc 、およびdの統計を収集します。ここで、列bPREDICATE COLUMNであり、列cdはインデックス列です。

SET GLOBAL tidb_enable_column_tracking = ON; Query OK, 0 rows affected (0.00 sec) CREATE TABLE t (a INT, b INT, c INT, d INT, INDEX idx_c_d(c, d)); Query OK, 0 rows affected (0.00 sec) -- The optimizer uses the statistics on column b in this query. SELECT * FROM t WHERE b > 1; Empty set (0.00 sec) -- After waiting for a period of time (100 * stats-lease), TiDB writes the collected `PREDICATE COLUMNS` to mysql.column_stats_usage. -- Specify `last_used_at IS NOT NULL` to show the `PREDICATE COLUMNS` collected by TiDB. SHOW COLUMN_STATS_USAGE WHERE db_name = 'test' AND table_name = 't' AND last_used_at IS NOT NULL; +---------+------------+----------------+-------------+---------------------+------------------+ | Db_name | Table_name | Partition_name | Column_name | Last_used_at | Last_analyzed_at | +---------+------------+----------------+-------------+---------------------+------------------+ | test | t | | b | 2022-01-05 17:21:33 | NULL | +---------+------------+----------------+-------------+---------------------+------------------+ 1 row in set (0.00 sec) ANALYZE TABLE t PREDICATE COLUMNS; Query OK, 0 rows affected, 1 warning (0.03 sec) -- Specify `last_analyzed_at IS NOT NULL` to show the columns for which statistics have been collected. SHOW COLUMN_STATS_USAGE WHERE db_name = 'test' AND table_name = 't' AND last_analyzed_at IS NOT NULL; +---------+------------+----------------+-------------+---------------------+---------------------+ | Db_name | Table_name | Partition_name | Column_name | Last_used_at | Last_analyzed_at | +---------+------------+----------------+-------------+---------------------+---------------------+ | test | t | | b | 2022-01-05 17:21:33 | 2022-01-05 17:23:06 | | test | t | | c | NULL | 2022-01-05 17:23:06 | | test | t | | d | NULL | 2022-01-05 17:23:06 | +---------+------------+----------------+-------------+---------------------+---------------------+ 3 rows in set (0.00 sec)

インデックスの統計を収集する

IndexNameList in TableNameのすべてのインデックスの統計を収集するには、次の構文を使用します。

ANALYZE TABLE TableName INDEX [IndexNameList] [WITH NUM BUCKETS|TOPN|CMSKETCH DEPTH|CMSKETCH WIDTH]|[WITH NUM SAMPLES|WITH FLOATNUM SAMPLERATE];

IndexNameListが空の場合、この構文はTableName内のすべてのインデックスの統計を収集します。

注記:

収集前後の統計情報の一貫性を確保するために、 tidb_analyze_version2の場合、この構文はインデックスだけでなく、テーブル全体 (すべての列とインデックスを含む) の統計を収集します。

パーティションの統計を収集する

  • PartitionNameList in TableNameのすべてのパーティションの統計を収集するには、次の構文を使用します。

    ANALYZE TABLE TableName PARTITION PartitionNameList [WITH NUM BUCKETS|TOPN|CMSKETCH DEPTH|CMSKETCH WIDTH]|[WITH NUM SAMPLES|WITH FLOATNUM SAMPLERATE];
  • PartitionNameList in TableNameのすべてのパーティションのインデックス統計を収集するには、次の構文を使用します。

    ANALYZE TABLE TableName PARTITION PartitionNameList INDEX [IndexNameList] [WITH NUM BUCKETS|TOPN|CMSKETCH DEPTH|CMSKETCH WIDTH]|[WITH NUM SAMPLES|WITH FLOATNUM SAMPLERATE];
  • テーブル内の一部のパーティションのいくつかの列の統計を収集するだけが必要な場合は、次の構文を使用します。

    ANALYZE TABLE TableName PARTITION PartitionNameList [COLUMNS ColumnNameList|PREDICATE COLUMNS|ALL COLUMNS] [WITH NUM BUCKETS|TOPN|CMSKETCH DEPTH|CMSKETCH WIDTH]|[WITH NUM SAMPLES|WITH FLOATNUM SAMPLERATE];

動的プルーニングモードでパーティションテーブルの統計を収集する

動的剪定モードでパーティション化されたテーブルにアクセスすると、TiDB はテーブル レベルの統計 (GlobalStats と呼ばれる) を収集します。現在、GlobalStats はすべてのパーティションの統計から集計されます。動的プルーニング モードでは、パーティションテーブルの統計の更新によって GlobalStats の更新がトリガーされることがあります。

注記:

  • GlobalStats 更新がトリガーされ、 tidb_skip_missing_partition_statsOFF場合:

    • 一部のパーティションに統計がない場合 (分析されたことがない新しいパーティションなど)、GlobalStats の生成が中断され、パーティションに統計がないことを示す警告メッセージが表示されます。
    • 特定のパーティションに一部の列の統計情報がない場合 (これらのパーティションで分析用に異なる列が指定されている場合)、これらの列の統計情報が集計されるときに GlobalStats の生成が中断され、特定のパーティションに一部の列の統計情報が存在しないことを示す警告メッセージが表示されます。
  • GlobalStats 更新がトリガーされ、 tidb_skip_missing_partition_statsON場合:

    一部のパーティションのすべての列または一部の列の統計が欠落している場合、TiDB は GlobalStats を生成するときにこれらの欠落しているパーティションの統計をスキップするため、GlobalStats の生成には影響しません。

  • 動的プルーニング モードでは、パーティションとテーブルの Analyze 構成は同じである必要があります。したがって、 ANALYZE TABLE TableName PARTITION PartitionNameListステートメントの後にCOLUMNS構成を指定したり、 WITHの後にOPTIONS構成を指定したりした場合、TiDB はそれらを無視し、警告を返します。

自動更新

INSERTDELETE 、またはUPDATEステートメントの場合、TiDB は行数と変更された行数を自動的に更新します。TiDB はこの情報を定期的に保持し、更新サイクルは 20 * stats-leaseです。デフォルト値stats-lease3sです。

関連するシステム変数

統計の自動更新に関連する 3 つのシステム変数は次のとおりです。

システム変数デフォルト値説明
tidb_auto_analyze_ratio0.5自動更新の閾値
tidb_auto_analyze_start_time00:00 +0000TiDBが自動更新を実行できる1日の開始時刻
tidb_auto_analyze_end_time23:59 +0000TiDBが自動更新を実行できる1日の終了時刻
tidb_auto_analyze_partition_batch_size1パーティションテーブルを分析するときに TiDB が自動的に分析するパーティションの数 (つまり、パーティションテーブルの統計を自動的に更新するとき)

テーブル内の変更された行数とtblの行の合計数の比率がtidb_auto_analyze_ratioより大きく、現在の時刻がtidb_auto_analyze_start_timeからtidb_auto_analyze_end_time間である場合、TiDB はバックグラウンドでANALYZE TABLE tblステートメントを実行し、このテーブルの統計を自動的に更新します。

小さなテーブルで少量のデータを変更すると、頻繁に自動更新がトリガーされる状況を回避するために、テーブルの行数が 1000 未満の場合、そのようなデータ変更によって TiDB の自動更新がトリガーされません。 SHOW STATS_METAステートメントを使用して、テーブル内の行数を表示できます。

注記:

現在、自動更新では、手動ANALYZEで入力した設定項目は記録されません。そのため、 WITH構文を使用してANALYZEの収集動作を制御する場合は、統計情報を収集するためのスケジュールされたタスクを手動で設定する必要があります。

自動更新を無効にする

統計の自動更新によって過剰なリソースが消費され、オンライン アプリケーションの操作に影響が出る場合は、 tidb_enable_auto_analyzeシステム変数を使用して無効にすることができます。

バックグラウンドのANALYZEタスクを終了する

TiDB v6.0 以降、TiDB はKILLステートメントを使用してバックグラウンドで実行されているANALYZEタスクを終了することをサポートしています。バックグラウンドで実行されているANALYZEタスクが大量のリソースを消費し、アプリケーションに影響を与えていることがわかった場合は、次の手順を実行してANALYZEタスクを終了できます。

  1. 次の SQL ステートメントを実行します。

    SHOW ANALYZE STATUS

    結果のinstance列目とprocess_id列目を確認すると、TiDB インスタンスのアドレスとバックグラウンドANALYZEタスクのタスクIDを取得できます。

  2. バックグラウンドで実行されているANALYZEタスクを終了します。

    ANALYZEタスクを終了するには、 KILL TIDB ${id};ステートメントを実行します。ここで、 ${id}前の手順で取得したバックグラウンドANALYZEタスクのIDです。

KILLステートメントの詳細については、 KILLを参照してください。

ANALYZE同時実行を制御する

ANALYZEステートメントを実行すると、システム変数を使用して同時実行性を調整し、システムへの影響を制御できます。

関連するシステム変数の関係を以下に示します。

analyze_concurrency

tidb_build_stats_concurrencytidb_build_sampling_stats_concurrencytidb_analyze_partition_concurrency 、上の図に示すように、上流と下流の関係にあります。実際の合計同時実行数は、 tidb_build_stats_concurrency * ( tidb_build_sampling_stats_concurrency + tidb_analyze_partition_concurrency ) です。これらの変数を変更するときは、それぞれの値を同時に考慮する必要があります。 tidb_analyze_partition_concurrencytidb_build_sampling_stats_concurrencytidb_build_stats_concurrencyの順に 1 つずつ調整し、システムへの影響を観察することをお勧めします。これら 3 つの変数の値が大きいほど、システムのリソース オーバーヘッドが大きくなります。

tidb_build_stats_concurrency

ANALYZEステートメントを実行すると、タスクは複数の小さなタスクに分割されます。各タスクは、1 つの列またはインデックスの統計情報のみを処理します。 tidb_build_stats_concurrency変数を使用して、同時実行される小さなタスクの数を制御できます。デフォルト値は2です。v7.4.0 以前のバージョンでは、デフォルト値は4です。

tidb_build_sampling_stats_concurrency

通常の列を分析する場合、 tidb_build_sampling_stats_concurrency使用してサンプリング タスクの実行の同時実行を制御できます。デフォルト値は2です。

tidb_analyze_partition_concurrency

ANALYZEステートメントを実行する場合、 tidb_analyze_partition_concurrency使用して、パーティションテーブルの統計の読み取りと書き込みの同時実行を制御できます。デフォルト値は2です。v7.4.0 以前のバージョンの場合、デフォルト値は1です。

tidb_distsql_scan_concurrency

通常の列を分析する場合、 tidb_distsql_scan_concurrency変数を使用して、一度に読み取るリージョンの数を制御できます。デフォルト値は15です。値を変更するとクエリのパフォーマンスに影響することに注意してください。値を慎重に調整してください。

tidb_index_serial_scan_concurrency

インデックス列を分析する場合、 tidb_index_serial_scan_concurrency変数を使用して、一度に読み取るリージョンの数を制御できます。デフォルト値は1です。値を変更するとクエリのパフォーマンスに影響することに注意してください。値を慎重に調整してください。

ANALYZE構成を永続化する

v5.4.0 以降、TiDB はいくつかのANALYZEつの構成の永続化をサポートしています。この機能により、将来の統計収集に既存の構成を簡単に再利用できます。

永続性をサポートするANALYZE構成は次のとおりです。

構成対応するANALYZE構文
ヒストグラムバケットの数バケット数
トップNの数番号付きトップ
サンプル数サンプル数
サンプリングレートFLOATNUM SAMPLERATE 付き
ANALYZE列タイプAnalyzeColumnOption ::= ( 'すべての列'
ANALYZE列目ColumnNameList ::= 識別子 ( ',' 識別子 )*

ANALYZE構成の永続性を有効にする

ANALYZE構成の永続性機能は、デフォルトで無効になっています。この機能を有効にするには、システム変数tidb_persist_analyze_optionsONであることを確認し、システム変数tidb_analyze_version2に設定します。

この機能を使用すると、ステートメントを手動で実行するときに、 ANALYZEステートメントで指定された永続性設定を記録できます。記録されると、次回 TiDB が統計を自動的に更新するか、これらの設定を指定せずに手動で統計を収集するときに、TiDB は記録された設定に従って統計を収集します。

auto analyze操作に使用される特定のテーブルに保存されている構成を照会するには、次の SQL ステートメントを使用できます。

SELECT sample_num, sample_rate, buckets, topn, column_choice, column_ids FROM mysql.analyze_options opt JOIN information_schema.tables tbl ON opt.table_id = tbl.tidb_table_id WHERE tbl.table_schema = '{db_name}' AND tbl.table_name = '{table_name}';

TiDB は、最新のANALYZEステートメントで指定された新しい構成を使用して、以前に記録された永続構成を上書きします。たとえば、 ANALYZE TABLE t WITH 200 TOPN;実行すると、 ANALYZEステートメントの上位 200 個の値が設定されます。続いてANALYZE TABLE t WITH 0.1 SAMPLERATE;を実行すると、 ANALYZE TABLE t WITH 200 TOPN, 0.1 SAMPLERATE;と同様に、上位 200 個の値と auto ANALYZEステートメントのサンプリング レート 0.1 の両方が設定されます。

ANALYZE構成の永続性を無効にする

ANALYZE構成の永続性機能を無効にするには、 tidb_persist_analyze_optionsシステム変数をOFFに設定します。 ANALYZE構成の永続性機能はtidb_analyze_version = 1には適用されないため、 tidb_analyze_version = 1を設定することでもこの機能を無効にすることができます。

ANALYZE構成の永続性機能を無効にした後、TiDB は永続化された構成レコードをクリアしません。したがって、この機能を再度有効にすると、TiDB は以前に記録された永続的な構成を使用して統計を収集し続けます。

注記:

ANALYZE構成の永続性機能を再度有効にしたときに、以前に記録された永続性構成が最新のデータに適用できなくなった場合は、 ANALYZEステートメントを手動で実行し、新しい永続性構成を指定する必要があります。

統計情報を収集するためのメモリ割り当て

TiDB v6.1.0 以降では、システム変数tidb_mem_quota_analyzeを使用して、TiDB で統計を収集するためのメモリクォータを制御できます。

適切な値tidb_mem_quota_analyzeを設定するには、クラスターのデータ サイズを考慮してください。デフォルトのサンプリング レートを使用する場合、主な考慮事項は、列の数、列値のサイズ、および TiDB のメモリ構成です。最大値と最小値を構成するときは、次の提案を考慮してください。

注記:

以下の提案は参考用です。実際のシナリオに基づいて値を設定する必要があります。

  • 最小値: TiDB が最も多くの列を持つテーブルから統計を収集する場合の最大メモリ使用量よりも大きくする必要があります。おおよその目安: TiDB がデフォルト設定を使用して 20 列のテーブルから統計を収集する場合、最大メモリ使用量は約 800 MiB です。TiDB がデフォルト設定を使用して 160 列のテーブルから統計を収集する場合、最大メモリ使用量は約 5 GiB です。
  • 最大値: TiDB が統計を収集していない場合は、使用可能なメモリよりも小さくする必要があります。

ANALYZE状態のビュー

ANALYZEステートメントを実行するときに、次の SQL ステートメントを使用してANALYZEの現在の状態を表示できます。

SHOW ANALYZE STATUS [ShowLikeOrWhere]

このステートメントはANALYZEの状態を返します。 ShowLikeOrWhereを使用して必要な情報をフィルタリングできます。

現在、 SHOW ANALYZE STATUSステートメントは次の 11 列を返します。

カラム名説明
テーブルスキーマデータベース名
テーブル名テーブル名
パーティション名パーティション名
求人情報タスク情報。インデックスが分析される場合、この情報にはインデックス名が含まれます。 tidb_analyze_version =2場合、この情報にはサンプル レートなどの構成項目が含まれます。
処理された行分析された行数
開始時間タスクが開始される時間
failedの状態running pending含むfinished
失敗理由タスクが失敗した理由。実行が成功した場合、値はNULLなります。
実例タスクを実行するTiDBインスタンス
プロセスIDタスクを実行するプロセスID

TiDB v6.1.0 以降では、 SHOW ANALYZE STATUSステートメントはクラスター レベルのタスクの表示をサポートします。TiDB を再起動した後でも、このステートメントを使用して再起動前のタスク レコードを表示できます。TiDB v6.1.0 より前では、 SHOW ANALYZE STATUSステートメントはインスタンス レベルのタスクのみを表示でき、タスク レコードは TiDB の再起動後にクリアされます。

SHOW ANALYZE STATUS最新のタスク レコードのみを表示します。TiDB v6.1.0 以降では、システム テーブルmysql.analyze_jobsを通じて過去 7 日間の履歴タスクを表示できます。

tidb_mem_quota_analyzeが設定され、TiDB のバックグラウンドで実行されている自動ANALYZEタスクがこのしきい値を超えるメモリを使用すると、タスクは再試行されます。 SHOW ANALYZE STATUSステートメントの出力で、失敗したタスクと再試行されたタスクを確認できます。

tidb_max_auto_analyze_timeが 0 より大きく、TiDB のバックグラウンドで実行されている自動ANALYZEタスクにこのしきい値を超える時間がかかる場合、タスクは終了します。

mysql> SHOW ANALYZE STATUS [ShowLikeOrWhere]; +--------------+------------+----------------+-------------------------------------------------------------------------------------------+----------------+---------------------+---------------------+----------+-------------------------------------------------------------------------------| | Table_schema | Table_name | Partition_name | Job_info | Processed_rows | Start_time | End_time | State | Fail_reason | +--------------+------------+----------------+-------------------------------------------------------------------------------------------+----------------+---------------------+---------------------+----------+-------------------------------------------------------------------------------| | test | sbtest1 | | retry auto analyze table all columns with 100 topn, 0.055 samplerate | 2000000 | 2022-05-07 16:41:09 | 2022-05-07 16:41:20 | finished | NULL | | test | sbtest1 | | auto analyze table all columns with 100 topn, 0.5 samplerate | 0 | 2022-05-07 16:40:50 | 2022-05-07 16:41:09 | failed | analyze panic due to memory quota exceeds, please try with smaller samplerate |

統計情報をビュー

次のステートメントを使用して統計ステータスを表示できます。

テーブルのメタデータ

SHOW STATS_METAステートメントを使用すると、行の合計数と更新された行の数を表示できます。

SHOW STATS_META [ShowLikeOrWhere];

ShowLikeOrWhereOptの構文は次のとおりです。

ShowLikeOrWhereOpt

現在、 SHOW STATS_METAステートメントは次の 6 つの列を返します。

カラム名説明
db_nameデータベース名
table_nameテーブル名
partition_nameパーティション名
update_time更新の時刻
modify_count変更された行の数
row_count行の総数

注記:

TiDB が DML ステートメントに従って合計行数と変更行数を自動的に更新すると、 update_timeも更新されます。したがって、 update_time必ずしもANALYZEステートメントが最後に実行された時刻を示すわけではありません。

テーブルの健全性状態

SHOW STATS_HEALTHYステートメントを使用すると、テーブルの正常性状態を確認し、統計の精度を大まかに見積もることができます。 modify_count >= row_countの場合、正常性状態は 0 です。 modify_count < row_countの場合、正常性状態は (1 - modify_count / row_count ) * 100 です。

構文は次のとおりです。

SHOW STATS_HEALTHY [ShowLikeOrWhere];

SHOW STATS_HEALTHYのあらすじは、

ShowStatsHealthy

現在、 SHOW STATS_HEALTHYステートメントは次の 4 つの列を返します。

カラム名説明
db_nameデータベース名
table_nameテーブル名
partition_nameパーティション名
healthyテーブルの健康状態

列のメタデータ

SHOW STATS_HISTOGRAMSステートメントを使用すると、すべての列の異なる値の数とNULLの数を表示できます。

構文は次のとおりです。

SHOW STATS_HISTOGRAMS [ShowLikeOrWhere]

このステートメントは、すべての列の異なる値の数とNULLの数を返します。 ShowLikeOrWhereを使用して、必要な情報をフィルター処理できます。

現在、 SHOW STATS_HISTOGRAMSステートメントは次の 10 列を返します。

カラム名説明
db_nameデータベース名
table_nameテーブル名
partition_nameパーティション名
column_name列名( is_index0の場合)またはインデックス名( is_index1の場合)
is_indexインデックス列であるかどうか
update_time更新の時刻
distinct_count異なる値の数
null_countNULLの数
avg_col_size列の平均長さ
相関列と整数主キーのピアソン相関係数。2つの列間の関連の度合いを示します。

ヒストグラムのバケット

SHOW STATS_BUCKETSステートメントを使用して、ヒストグラムの各バケットを表示できます。

構文は次のとおりです。

SHOW STATS_BUCKETS [ShowLikeOrWhere]

図は以下のとおりです。

SHOW STATS_BUCKETS

このステートメントは、すべてのバケットに関する情報を返します。 ShowLikeOrWhere使用して、必要な情報をフィルタリングできます。

現在、 SHOW STATS_BUCKETSステートメントは次の 11 列を返します。

カラム名説明
db_nameデータベース名
table_nameテーブル名
partition_nameパーティション名
column_name列名( is_index0の場合)またはインデックス名( is_index1の場合)
is_indexインデックス列であるかどうか
bucket_idバケットのID
countバケットと前のバケットに含まれるすべての値の数
repeats最大値の発生回数
lower_bound最小値
upper_bound最大値
Ndvバケット内の異なる値の数。このフィールドは非推奨であり、値が不正確なため常に0表示されます。

トップN情報

SHOW STATS_TOPNステートメントを使用すると、TiDB によって現在収集されている Top-N 情報を表示できます。

構文は次のとおりです。

SHOW STATS_TOPN [ShowLikeOrWhere];

現在、 SHOW STATS_TOPNステートメントは次の 7 つの列を返します。

カラム名説明
db_nameデータベース名
table_nameテーブル名
partition_nameパーティション名
column_name列名( is_index0の場合)またはインデックス名( is_index1の場合)
is_indexインデックス列であるかどうか
valueこの列の値
count値が何回出現するか

統計情報を削除

統計を削除するには、 DROP STATSステートメントを実行します。

DROP STATS TableName

上記のステートメントは、 TableNameのすべての統計を削除します。パーティションテーブルが指定されている場合、このステートメントは、このテーブル内のすべてのパーティションの統計と、動的プルーニング モードで生成された GlobalStats を削除します。

DROP STATS TableName PARTITION PartitionNameList;

上記のステートメントは、 PartitionNameList内の指定されたパーティションの統計情報のみを削除します。

DROP STATS TableName GLOBAL;

上記のステートメントは、指定されたテーブルの動的プルーニング モードで生成された GlobalStats のみを削除します。

負荷統計

注記:

TiDB Cloudサーバーレスクラスターでは読み込み統計は利用できません。

デフォルトでは、列統計のサイズに応じて、TiDB は次のように異なる方法で統計をロードします。

  • メモリを少量しか消費しない統計 (count、distinctCount、nullCount など) の場合、列データが更新されている限り、TiDB は対応する統計をメモリに自動的にロードし、SQL 最適化ステージで使用します。
  • 大量のメモリを消費する統計 (ヒストグラム、TopN、Count-Min Sketch など) の場合、SQL 実行のパフォーマンスを確保するために、TiDB はオンデマンドで統計を非同期的にロードします。ヒストグラムを例に挙げると、TiDB は、オプティマイザがその列のヒストグラム統計を使用する場合にのみ、その列のヒストグラム統計をメモリにロードします。オンデマンドの非同期統計のロードは、SQL 実行のパフォーマンスには影響しませんが、SQL 最適化に不完全な統計を提供する可能性があります。

v5.4.0 以降、TiDB では統計の同期ロード機能が導入されています。この機能により、SQL ステートメントを実行するときに、TiDB は大規模な統計 (ヒストグラム、TopN、Count-Min Sketch 統計など) をメモリにメモリにロードできるようになり、SQL 最適化の統計の完全性が向上します。

この機能を有効にするには、 tidb_stats_load_sync_waitシステム変数の値を、SQL 最適化が完全な列統計を同期的にロードするまで待機できる最大タイムアウト (ミリ秒単位) に設定します。この変数のデフォルト値は100で、この機能が有効であることを示します。

統計の同期ロード機能を有効にした後、 tidb_stats_load_pseudo_timeoutシステム変数の値を変更することで、SQL 最適化の待機時間がタイムアウトに達したときの TiDB の動作を制御できます。この変数のデフォルト値はONで、タイムアウト後、SQL 最適化プロセスはどの列でもヒストグラム、TopN、または CMSketch 統計を使用しないことを示します。この変数がOFFに設定されている場合、タイムアウト後、SQL 実行は失敗します。

輸入と輸出の統計

注記:

このセクションはTiDB Cloudには適用されません。

輸出統計

統計をエクスポートするためのインターフェースは次のとおりです。

  • ${db_name}データベース内の${table_name}テーブルの JSON 形式の統計を取得するには:

    http://${tidb-server-ip}:${tidb-server-status-port}/stats/dump/${db_name}/${table_name}

    例えば:

    curl -s http://127.0.0.1:10080/stats/dump/test/t1 -o /tmp/t1.json
  • 特定の時間における${db_name}データベース内の${table_name}テーブルの JSON 形式の統計を取得するには:

    http://${tidb-server-ip}:${tidb-server-status-port}/stats/dump/${db_name}/${table_name}/${yyyyMMddHHmmss}

輸入統計

注記:

MySQL クライアントを起動するときは、 --local-infile=1オプションを使用します。

通常、インポートされた統計は、エクスポート インターフェイスを使用して取得された JSON ファイルを参照します。

構文:

LOAD STATS 'file_name'

file_nameはインポートする統計のファイル名です。

ロック統計

v6.5.0 以降、TiDB は統計のロックをサポートしています。テーブルまたはパーティションの統計がロックされると、テーブルの統計は変更できなくなり、テーブルに対してANALYZEステートメントを実行することもできなくなります。例:

テーブルtを作成し、そこにデータを挿入します。テーブルtの統計がロックされていない場合、 ANALYZEステートメントは正常に実行できます。

mysql> CREATE TABLE t(a INT, b INT); Query OK, 0 rows affected (0.03 sec) mysql> INSERT INTO t VALUES (1,2), (3,4), (5,6), (7,8); Query OK, 4 rows affected (0.00 sec) Records: 4 Duplicates: 0 Warnings: 0 mysql> ANALYZE TABLE t; Query OK, 0 rows affected, 1 warning (0.02 sec) mysql> SHOW WARNINGS; +-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Level | Code | Message | +-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Note | 1105 | Analyze use auto adjusted sample rate 1.000000 for table test.t, reason to use this rate is "Row count in stats_meta is much smaller compared with the row count got by PD, use min(1, 15000/4) as the sample-rate=1" | +-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)

テーブルtの統計をロックし、 ANALYZEを実行します。警告メッセージは、 ANALYZEステートメントがテーブルtをスキップしたことを示します。

mysql> LOCK STATS t; Query OK, 0 rows affected (0.00 sec) mysql> SHOW STATS_LOCKED; +---------+------------+----------------+--------+ | Db_name | Table_name | Partition_name | Status | +---------+------------+----------------+--------+ | test | t | | locked | +---------+------------+----------------+--------+ 1 row in set (0.01 sec) mysql> ANALYZE TABLE t; Query OK, 0 rows affected, 2 warnings (0.00 sec) mysql> SHOW WARNINGS; +---------+------+-----------------------------------------------------------------------------------------------------------------------------------------+ | Level | Code | Message | +---------+------+-----------------------------------------------------------------------------------------------------------------------------------------+ | Note | 1105 | Analyze use auto adjusted sample rate 1.000000 for table test.t, reason to use this rate is "use min(1, 110000/8) as the sample-rate=1" | | Warning | 1105 | skip analyze locked table: test.t | +---------+------+-----------------------------------------------------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec)

tおよびANALYZEの統計のロックを解除すると、再度正常に実行できます。

mysql> UNLOCK STATS t; Query OK, 0 rows affected (0.01 sec) mysql> ANALYZE TABLE t; Query OK, 0 rows affected, 1 warning (0.03 sec) mysql> SHOW WARNINGS; +-------+------+-----------------------------------------------------------------------------------------------------------------------------------------+ | Level | Code | Message | +-------+------+-----------------------------------------------------------------------------------------------------------------------------------------+ | Note | 1105 | Analyze use auto adjusted sample rate 1.000000 for table test.t, reason to use this rate is "use min(1, 110000/8) as the sample-rate=1" | +-------+------+-----------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)

さらに、 LOCK STATS使用してパーティションの統計をロックすることもできます。次に例を示します。

パーティション テーブルtを作成し、そこにデータを挿入します。パーティションp1の統計がロックされていない場合、 ANALYZEステートメントは正常に実行できます。

mysql> CREATE TABLE t(a INT, b INT) PARTITION BY RANGE (a) (PARTITION p0 VALUES LESS THAN (10), PARTITION p1 VALUES LESS THAN (20), PARTITION p2 VALUES LESS THAN (30)); Query OK, 0 rows affected (0.03 sec) mysql> INSERT INTO t VALUES (1,2), (3,4), (5,6), (7,8); Query OK, 4 rows affected (0.00 sec) Records: 4 Duplicates: 0 Warnings: 0 mysql> ANALYZE TABLE t; Query OK, 0 rows affected, 6 warning (0.02 sec) mysql> SHOW WARNINGS; +---------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Level | Code | Message | +---------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Warning | 1105 | disable dynamic pruning due to t has no global stats | | Note | 1105 | Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p0, reason to use this rate is "Row count in stats_meta is much smaller compared with the row count got by PD, use min(1, 15000/4) as the sample-rate=1" | | Warning | 1105 | disable dynamic pruning due to t has no global stats | | Note | 1105 | Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p1, reason to use this rate is "TiDB assumes that the table is empty, use sample-rate=1" | | Warning | 1105 | disable dynamic pruning due to t has no global stats | | Note | 1105 | Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p2, reason to use this rate is "TiDB assumes that the table is empty, use sample-rate=1" | +---------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 6 rows in set (0.01 sec)

パーティションp1の統計をロックし、 ANALYZEを実行します。警告メッセージは、 ANALYZEステートメントがパーティションp1をスキップしたことを示します。

mysql> LOCK STATS t PARTITION p1; Query OK, 0 rows affected (0.00 sec) mysql> SHOW STATS_LOCKED; +---------+------------+----------------+--------+ | Db_name | Table_name | Partition_name | Status | +---------+------------+----------------+--------+ | test | t | p1 | locked | +---------+------------+----------------+--------+ 1 row in set (0.00 sec) mysql> ANALYZE TABLE t PARTITION p1; Query OK, 0 rows affected, 2 warnings (0.01 sec) mysql> SHOW WARNINGS; +---------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Level | Code | Message | +---------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Note | 1105 | Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p1, reason to use this rate is "TiDB assumes that the table is empty, use sample-rate=1" | | Warning | 1105 | skip analyze locked table: test.t partition (p1) | +---------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec)

パーティションp1ANALYZEの統計情報のロック解除を再度正常に実行できます。

mysql> UNLOCK STATS t PARTITION p1; Query OK, 0 rows affected (0.00 sec) mysql> ANALYZE TABLE t PARTITION p1; Query OK, 0 rows affected, 1 warning (0.01 sec) mysql> SHOW WARNINGS; +-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Level | Code | Message | +-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Note | 1105 | Analyze use auto adjusted sample rate 1.000000 for table test.t's partition p1, reason to use this rate is "TiDB assumes that the table is empty, use sample-rate=1" | +-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)

統計情報のロックの動作

  • パーティションテーブルの統計をロックすると、パーティションテーブルのすべてのパーティションの統計がロックされます。
  • テーブルまたはパーティションを切り捨てると、テーブルまたはパーティションの統計ロックが解除されます。

次の表は、統計のロックの動作を示しています。

テーブル全体を削除するテーブル全体を切り捨てるパーティションを切り捨てる新しいパーティションを作成するパーティションを削除するパーティションを再編成するパーティションを交換する
パーティションテーブルがロックされているロックが無効ですTiDBは古いテーブルを削除するためロックは無効になり、ロック情報も削除されます。/////
パーティションテーブルとテーブル全体がロックされているロックが無効ですTiDBは古いテーブルを削除するためロックは無効になり、ロック情報も削除されます。古いパーティションのロック情報は無効であり、新しいパーティションは自動的にロックされます新しいパーティションは自動的にロックされます削除されたパーティションのロック情報はクリアされ、テーブル全体のロックは引き続き有効になります。削除されたパーティションのロック情報はクリアされ、新しいパーティションは自動的にロックされますロック情報は交換されたテーブルに転送され、新しいパーティションは自動的にロックされます。
パーティションテーブルで、一部のパーティションのみがロックされているロックが無効ですTiDBは古いテーブルを削除するためロックは無効になり、ロック情報も削除されます。TiDBは古いテーブルを削除するためロックは無効になり、ロック情報も削除されます。/削除されたパーティションのロック情報はクリアされます削除されたパーティションのロック情報はクリアされますロック情報は交換テーブルに転送される

参照

このページは役に立ちましたか?