This page contains information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. As with all projects, the items mentioned on this page are subject to change or delay. The development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc.
StatusAuthorsCoachDRIsOwning StageCreated
proposed -

データベースのスケーラビリティ:GitLab.comでは、ディスク上のテーブルサイズを100GB未満に制限します。

このドキュメントは、GitLab.comのテーブルサイズの削減と制限に向けた提案です。テーブルサイズをある閾値に制限することで、測定可能な目標を設定します。これは、データベースの焦点化と意思決定を推進するための指標として使われます。GitLab.comが成長するにつれて、私たちは違反の防止やその他の修正のためにどのテーブルに取り組む必要があるかを継続的に再評価しています。

これは厳密なルールではなく、テーブルを分割したりサイズを小さくしたりする作業が必要であることを示すものです。

これは、全体像を描くDatabase Shardingの設計図との関連で読まれることを意図しています。ここでの提案は、ストレージ要件を減らし、データモデリングを改善することを目的とした、以下の「デブロートステップ」の一部と考えられます。パーティショニングは標準的なツールベルトの一部です。可能であれば、物理的なテーブルサイズを大幅に削減するソリューションとして、すでにパーティショニングを使用することができます。パーティショニングは標準的なツールベルトの一部であり、可能であれば、物理的なテーブルサイズを大幅に削減するためのソリューションとしてパーティショニングを使用することができます。

graph LR Fe(Pick feature) --> D D[(Database)] --> De De[Debloating] --> Dc Dc[Decomposition] --> P P[Partitioning] --> S S[Sharding] --> R P --> M M[Microservices] --> R R{Repeat?} --> Fe style De fill:#fca326 style P fill:#fc6d26

動機GitLab.comの安定性とパフォーマンス

GitLab.comの大きなテーブルは、オペレーションにとっても開発者にとっても大きな問題です。それらは様々な問題を引き起こします:

  1. クエリの時間、ひいてはアプリケーション全体のパフォーマンスの低下
  2. テーブルのメンテナンスにコストがかかるGitLab.comではバキューム・アクティビティが重要な問題となっています。大規模なテーブルでは1日に1回という頻度の低い処理しか行われず、バキュームの実行には何時間もかかります。これは様々な悪影響を及ぼし、非常に大きなテーブルはデータベースの一見無関係に見える部分にも影響を与える可能性があります。
  3. 大規模なテーブルのデータマイグレーションは、実装が非常に複雑で、開発者のオーバーヘッドになります。GitLab.comの安定性の問題を引き起こす可能性があり、大きなデータセットで実行するのに長い時間がかかります。
  4. インデックスのサイズは重要です。インデックスの小さな部分がメモリに保持されるため、パフォーマンスに直接影響します。また、インデックスのメンテナーも難しくなります(リパッキングを考えてみてください)。
  5. インデックスの作成時間が大幅に増加します。2021年では、1つのB-Treeインデックスに対して、B-Treeの作成に最大6時間かかっています。これは頻繁にデプロイする能力に影響を与え、バキューム関連の問題(クリーンアップの遅延)につながります。
  6. 私たちは緩和するために多くのインデックスを追加しがちですが、これは最終的に大きなオーバーヘッドを引き起こし、クエリプランナを混乱させる可能性があります。

使用例

最も顕著な例として、ci_builds テーブルの2021年6月現在のサイズは1.5TBで、31個のインデックスが関連付けられ、その合計サイズは1TBです。このテーブルの全体のディスク上のサイズは2.5 TBです。現在、毎月300GBずつ増加しています。対策を講じなければ、年末には5TB近くになると思われます。

以下の例は、非常に大きなテーブルがGitLab.comのインシデントの根本原因であることが多いことを示しています。

  1. バキューム・アクティビティが頻繁に行われず、長い間実行されているため、CIキューイングのクエリ・パフォーマンスが何度も低下しています。
  2. ci_buildsのような大規模なテーブルでは、インデックス作成にかかる時間は、混雑時には1.5時間から6時間の間で変動します。このプロセスは、マイグレーションが同期的に実行されるため、デプロイをブロックし、頻繁にデプロイする能力を低下させます。
  3. 大規模なインデックスの作成は、データベースのプライマリでのアクティビティを急増させます:
    1. merge_request_diff_commits テーブルでネットワークが高飽和状態になりました、
    2. 週末に定期的なインデックス再作成アクティビティが発生すると、WALキューが増大します(復旧目標に影響)、
    3. notes テーブル:メンテナンスのためにGINトリグラムインデックスを再作成することはほとんど不可能になり、他のバキュームオペレーションをブロックするため、最初の試行では12時間後に中止しなければなりませんでした。

GitLab.com上の問題のあるテーブル

これは、2021年6月中旬現在、GitLab.comにあるテーブルの総サイズ(インデックスサイズも含む)別にTOP30を表示したものです。table_size, index_size は、実際のデータと関連するインデックスそれぞれのディスク上のサイズです。percentage_of_total_database_size は、データベースサイズに対するテーブル総サイズの比率を表示しています。

見てわかるように、現在 1 TB を超える非常に大きなテーブルが存在し、それらは非常に大きなインデックスを持つ傾向があります。

もう1つの観察は、多数のインデックスを持つテーブルもあり、インデックス・サイズの合計が格納されているデータよりもかなり大きくなる可能性があるということです。例えば、deployments は30GBのサイズであり、さらに24のインデックスにまたがって123GBのインデックスデータがあります。

テーブル合計サイズテーブルサイズインデックスサイズインデックス数データベース全体のサイズに対する割合
ci_builds2975 GB1551 GB941 GB3022.7
merge_request_diff_commits1890 GB1454 GB414 GB214.4
ci_build_trace_sections1123 GB542 GB581 GB38.6
notes748 GB390 GB332 GB135.7
merge_request_diff_files575 GB481 GB88 GB14.4
events441 GB95 GB346 GB123.4
ci_job_artifacts397 GB187 GB210 GB103.0
ci_pipelines266 GB66 GB200 GB232.0
taggings238 GB60 GB179 GB51.8
ci_builds_metadata237 GB88 GB149 GB51.8
issues219 GB47 GB150 GB281.7
web_hook_logs_202103186 GB122 GB8416 MB31.4
ci_stages182 GB58 GB124 GB61.4
web_hook_logs_202105180 GB115 GB7868 MB31.4
merge_requests176 GB44 GB125 GB361.3
web_hook_logs_202104176 GB115 GB7472 MB31.3
web_hook_logs_202101169 GB112 GB7231 MB31.3
web_hook_logs_202102167 GB111 GB7106 MB31.3
sent_notifications166 GB88 GB79 GB31.3
web_hook_logs_202011163 GB113 GB7125 MB31.2
push_event_payloads162 GB114 GB48 GB11.2
web_hook_logs_202012159 GB106 GB6771 MB31.2
web_hook_logs_202106156 GB101 GB6752 MB31.2
deployments155 GB30 GB125 GB241.2
web_hook_logs_202010136 GB98 GB6116 MB31.0
web_hook_logs_202009114 GB82 GB5168 MB30.9
security_findings109 GB21 GB88 GB80.8
web_hook_logs_20200892 GB66 GB3983 MB30.7
resource_label_events66 GB47 GB19 GB60.5
merge_request_diffs63 GB39 GB22 GB50.5

ターゲットGitLab.com上のすべての物理テーブルがインデックスを含めて100GB未満

note
PostgreSQLの文脈では、物理テーブルは通常のテーブルかパーティショニングされたテーブルのパーティションです。

オペレーションの安定性を維持・向上し、開発者の負担を軽減するために、私たちはGitLab.comの物理テーブル(インデックスを含む)のテーブルサイズを100GB未満にすることを目標としています。これには多くのメリットがあります:

  1. クエリのパフォーマンスが向上し、クエリプランが安定します。
  2. バキューム実行時間を大幅に短縮し、バキューム実行の頻度を増やして健全な状態を維持することで、データベース・プライマリのオーバーヘッドを削減
  3. インデックスの作成時間が大幅に短縮(インデックスごとに読み込むデータが大幅に減少)
  4. インデックスのサイズが小さくなり、より効率的にメンテナーでき、メモリへの収まりが良くなります。
  5. データマイグレーションは推論しやすく、実装と実行に時間がかかりません。

この目標は現実的です:テーブルのサイズは、機能の使用状況、コードの変更、その他の要因に依存します。物理的なテーブルのサイズをきっちりと制限できるようなソリューションが常に見つかるとは限りません。しかし、それは許容範囲内であり、私たちは主にGitLab.comの状況をコントロール下に保つことを目指しています。私たちはGitLab.comの状況に合わせて取り組み、頻繁に再評価を行っています。

物理的なテーブルの最大サイズが一定になるような変更は可能ですが、必ずしもそうである必要はありません。例えば、テーブルを固定数のパーティションに分割するハッシュ・パーティショニングを考えてみましょう。時間の経過とともにデータが増加すると、個々のパーティションのサイズも大きくなり、最終的に再び閾値サイズに達する可能性があります。私たちはテーブルのサイズが一定になるように努力していますが、このような特性を持たず、かなりの時間状況を改善するような、より簡単なソリューションを出荷することも許容されます。

このように、リファクタリング後の物理テーブルの目標サイズは状況によって異なり、明確なルールはありません。過去のデータ増加を考慮し、物理テーブルが再び100GBの閾値に達する時期を予測することをお勧めします。これにより、モデルを再検討する必要が生じるまで、特定のソリューションがどのくらいの期間続くと予想されるかを理解することができます。

解決方法

テーブルサイズを小さくするための標準的なソリューションはありません!

  1. 保持:不要なデータを削除します。例えば、古いレコードや不要なレコードは期限切れにします。
  2. STIの削除: アンチパターンとされる単一テーブル継承をまだ数カ所で使用しています。これを再設計することで、データを複数のテーブルに分割することができます。
  3. インデックスの最適化:不要なインデックスを削除し、可能であれば重複するインデックスを統合します。
  4. データ型の最適化:データ型の決定をレビューし、可能であればデータ型を最適化(例:enumカラムにtextではなくintegerを使用)。
  5. パーティショニング:共通のアクセス・ディメンジョンがある場合は、パーティショニング・スキームを適用します。
  6. 正規化:関係モデリングをレビューし、正規化テクニックを適用して重複データを削除します。
  7. テーブルの垂直分割:カラムの使用法をレビューし、テーブルを縦に分割します。
  8. 外部化:大きなデータ型をデータベースから完全に移動します。例えば、JSONドキュメントは、特にフィルタリングに使用しない場合は、オブジェクトストレージなど、データベースの外部に保存した方が良いでしょう。
note
物理的なテーブルサイズを制限することを目標としていますが、パフォーマンスを維持または向上させることも目標と考えています。

正規化のようなソリューションでは、これはトレードオフの関係にあります。非正規化モデルは適切に使用された場合、クエリを高速化できますが、テーブルサイズは犠牲になります。モデルを正規化したり、テーブルを分割したり、データを外部化したりする場合は、パフォーマンスへの影響を理解し、パフォーマンスに大きな影響を与えないテーブルサイズを削減するソリューションを見つけるよう努めます。

取り組み例

エピック・データベースの効率化の下に、さらに多くの例が整理されています。

  1. のインデックスの数を減らします。ci_builds
  2. のコミッターと作成者の詳細の正規化と重複排除。merge_request_diff_commits
  3. の保持戦略ci_build_trace_sections
  4. 古い CI ジョブのメタデータをハード削除するワーカーの実装
  5. merge_request_diff_files < 100 GB のターゲット (エピック) に違反している場合

ゴール

~group::database](https://gitlab.com/groups/gitlab-org/-/epics/6211) のための[エピックは、目標の確立と伝達、そして目標達成のために必要な変更の特定と提案のための意思決定を推進します。これらの変更は、主にデータ(およびそれを使用する機能)を所有する各ステージグループによって推進されるべきであり、~group::database

GitLabデータベースチームと各ステージグループによって、問題のあるテーブルのソリューションを特定します。

ロール
Authorアンドレアス・ブランドル
エンジニアリングリーダークレイグ・ゴメス