📣
TiDB Cloud Premium はパブリックプレビュー中です。エンタープライズワークロード向けの無制限のスケーリング、即時の弾力性、高度なセキュリティを提供します。このページは自動翻訳されたものです。原文はこちらからご覧ください。

TiFlashディスクへの書き込み



このドキュメントでは、 TiFlash が計算中にデータをディスクに書き出す方法について説明します。

バージョン7.0.0以降、 TiFlashはメモリ負荷を軽減するために中間データをディスクに書き出す機能をサポートしています。以下のオペレーターがサポートされています。

  • 等価結合条件を持つハッシュ結合オペレーター
  • GROUP BYキーを持つハッシュ集計オペレーター
  • TopNオペレーターとウィンドウ関数のソートオペレーター

スピルのトリガー

TiFlash は、データをディスクに書き出すための 2つのトリガー メカニズムを提供します。

  • オペレーターレベルのスピル: 各オペレーターのデータスピルしきい値を指定することにより、 TiFlash がそのオペレーターのデータをディスクにスピルするタイミングを制御できます。
  • クエリレベルのスピル: TiFlashノードでのクエリの最大メモリ使用量とスピルのメモリ比率を指定することにより、 TiFlash がクエリでサポートされているオペレーターのデータを必要に応じてディスクにスピルするタイミングを制御できます。

オペレーターレベルのスピル

バージョン7.0.0以降、 TiFlashはオペレーターレベルでの自動スピルをサポートしています。以下のシステム変数を使用して、各オペレーターのデータスピルのしきい値を制御できます。オペレーターのメモリ使用量がしきい値を超えると、 TiFlashはそのオペレーターのスピルをトリガーします。

この例では、ハッシュ集計オペレーターのスピルを示すために、大量のメモリを消費する SQL 文を構築します。

  1. 環境を準備します。2ノードのTiFlashクラスターを作成し、TPCH-100データをインポートします。

  2. 以下のステートメントを実行してください。これらのステートメントは、 GROUP BYキーのハッシュ集計オペレーターのメモリ使用量を制限しません。

    SET tidb_max_bytes_before_tiflash_external_group_by = 0; SELECT l_orderkey, MAX(L_COMMENT), MAX(L_SHIPMODE), MAX(L_SHIPINSTRUCT), MAX(L_SHIPDATE), MAX(L_EXTENDEDPRICE) FROM lineitem GROUP BY l_orderkey HAVING SUM(l_quantity) > 314;
  3. TiFlashのログから、クエリは単一のTiFlashノードで 29.55 GiB のメモリを消費する必要があることがわかります。

    [DEBUG] [MemoryTracker.cpp:69] ["Peak memory usage (total): 29.55 GiB."] [source=MemoryTracker] [thread_id=468]
  4. 次のステートメントを実行します。このステートメントは、 GROUP BYキーを持つハッシュ集計オペレーターのメモリ使用量を10737418240(10 GiB)に制限します。

    SET tidb_max_bytes_before_tiflash_external_group_by = 10737418240; SELECT l_orderkey, MAX(L_COMMENT), MAX(L_SHIPMODE), MAX(L_SHIPINSTRUCT), MAX(L_SHIPDATE), MAX(L_EXTENDEDPRICE) FROM lineitem GROUP BY l_orderkey HAVING SUM(l_quantity) > 314;
  5. TiFlashのログを見ると、 tidb_max_bytes_before_tiflash_external_group_byを設定するとTiFlash が中間結果のスピルをトリガーし、クエリで使用されるメモリが大幅に削減されることがわかります。

    [DEBUG] [MemoryTracker.cpp:69] ["Peak memory usage (total): 12.80 GiB."] [source=MemoryTracker] [thread_id=110]

クエリレベルのスピル

TiFlash v7.4.0以降、クエリレベルでの自動スピルをサポートしています。この機能は、以下のシステム変数を使用して制御できます。

tiflash_mem_quota_query_per_nodetiflash_query_spill_ratio両方が 0 より大きい値に設定されている場合、クエリのメモリ使用量がtiflash_mem_quota_query_per_node * tiflash_query_spill_ratio超えると、 TiFlash はクエリでサポートされているオペレーターのスピルを自動的にトリガーします。

この例では、クエリレベルのスピルを示すために大量のメモリを消費する SQL文を構築します。

  1. 環境を準備します。2ノードのTiFlashクラスターを作成し、TPCH-100データをインポートします。

  2. 以下のステートメントを実行してください。これらのステートメントは、クエリのメモリ使用量や、 GROUP BYキーを持つハッシュ集計オペレーターのメモリ使用量を制限しません。

    SET tidb_max_bytes_before_tiflash_external_group_by = 0; SET tiflash_mem_quota_query_per_node = 0; SET tiflash_query_spill_ratio = 0; SELECT l_orderkey, MAX(L_COMMENT), MAX(L_SHIPMODE), MAX(L_SHIPINSTRUCT), MAX(L_SHIPDATE), MAX(L_EXTENDEDPRICE) FROM lineitem GROUP BY l_orderkey HAVING SUM(l_quantity) > 314;
  3. TiFlashのログから、クエリが単一のTiFlashノードで 29.55 GiB のメモリを消費していることがわかります。

    [DEBUG] [MemoryTracker.cpp:69] ["Peak memory usage (total): 29.55 GiB."] [source=MemoryTracker] [thread_id=468]
  4. 以下のステートメントを実行します。これらのステートメントは、 TiFlashノード上のクエリの最大メモリ使用量を5GiBに制限します。

    SET tiflash_mem_quota_query_per_node = 5368709120; SET tiflash_query_spill_ratio = 0.7; SELECT l_orderkey, MAX(L_COMMENT), MAX(L_SHIPMODE), MAX(L_SHIPINSTRUCT), MAX(L_SHIPDATE), MAX(L_EXTENDEDPRICE) FROM lineitem GROUP BY l_orderkey HAVING SUM(l_quantity) > 314;
  5. TiFlashのログから、クエリレベルのスピルを構成すると、 TiFlash中間結果のスピルがトリガーされ、クエリで使用されるメモリが大幅に削減されることがわかります。

    [DEBUG] [MemoryTracker.cpp:101] ["Peak memory usage (for query): 3.94 GiB."] [source=MemoryTracker] [thread_id=1547]

注記

  • ハッシュ集計オペレーターにGROUP BYキーがない場合、スピルはサポートされません。ハッシュ集計オペレーターに独自の集計関数が含まれている場合でも、スピルはサポートされません。

  • 現在、オペレーターレベルのスピルのしきい値は各オペレーターごとに個別に計算されます。2つのハッシュ集計オペレーターを含むクエリの場合、クエリレベルのスピルが設定されておらず、集計オペレーターのしきい値が10 GiBに設定されている場合、2つのハッシュ集計オペレーターは、それぞれのメモリ使用量が10 GiBを超えた場合にのみデータをスピルします。

  • 現在、ハッシュ集計オペレーターとTopN/Sortオペレーターは、リストアフェーズでマージ集計アルゴリズムとマージソートアルゴリズムを使用しています。そのため、これら2つのオペレーターはスピルを1ラウンドのみトリガーします。メモリ需要が非常に高く、リストアフェーズ中のメモリ使用量が依然としてしきい値を超えている場合、スピルは再度トリガーされません。

  • 現在、ハッシュ結合オペレーターはパーティションベースのスピル戦略を使用しています。リストアフェーズ中のメモリ使用量が依然としてしきい値を超える場合、スピルは再度トリガーされます。ただし、スピルの規模を制御するため、スピルの回数は3回に制限されています。3回目のスピル後もリストアフェーズ中のメモリ使用量が依然としてしきい値を超える場合、スピルは再度トリガーされません。

  • クエリレベルのスピルが設定されている場合 (つまり、 tiflash_mem_quota_query_per_nodetiflash_query_spill_ratio両方が 0 より大きい場合)、 TiFlash は個々のオペレーターのスピルしきい値を無視し、クエリレベルのスピルしきい値に基づいてクエリ内の関連するオペレーターのスピルを自動的にトリガーします。

  • クエリレベルのスピルが設定されている場合でも、クエリで使用されるオペレーターがスピルをサポートしていない場合、そのクエリの中間計算結果はディスクにスピルできません。この場合、そのクエリのメモリ使用量が関連するしきい値を超えると、 TiFlashはエラーを返し、クエリを終了します。

  • クエリレベルのスピルが構成されていて、クエリにスピルをサポートするオペレーターが含まれている場合でも、次のいずれかのシナリオでメモリしきい値を超えたためにクエリからエラーが返される可能性があります。

    • クエリ内のその他の非スピルオペレーターはメモリを大量に消費します。

    • スピルオペレーターは、タイムリーにディスクにスピルしません。

      スピルオペレーターが時間内にディスクにスピルしない状況に対処するには、メモリしきい値エラーを回避するためにtiflash_query_spill_ratio減らすことを試してください。

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