はじめに
本記事は JAWS DAYS 2025(2025/3/1)において PingCAP株式会社 Senior Solution Architect の 小板橋氏 が講演された「ここがつらいよ分散SQLデータベース」のレポートです。
公式セッション紹介
クラウド時代において、スケールアウトが可能な分散SQLデータベースは注目を集めています。
本セッションでは、分散SQLデータベースであるTiDBを題材に、分散SQLの仕組みと実運用のリアルな課題/辛みを解説します。
前半は、TiDBのアーキテクチャを技術的な観点から深掘りし、MVCC、分散トランザクション、Raft アルゴリズムに基づく分散一貫性といったコア技術について解説し、分散データベースがどのように一貫性とスケーラビリティを両立するのか、その設計思想を紐解きます。
後半では、実際の運用現場で直面する課題にフォーカスし、OLTPチューニングの研究とクエリ最適化の落とし穴、移行の高度化、運用のリアルといったポイントを包み隠さずお話しします。
良い面だけでなく、分散SQLデータベース特有の難しさとその対策についても共有します。
(引用:ここがつらいよ分散SQLデータベース)
発表資料
概要/おすすめポイント
本セッションではTiDBの紹介にとどまらず、内部のアーキテクチャーから実際の運用時に発生しやすい課題とその対策についても説明されており、TiDBを利用してみたい人には有用なセッションになっていたかと思います。
セッション内容の紹介
分散型SQLデータベース(≒NewSQL)の紹介
書き込み負荷に対しての性能が必要。
← GAFAによって NoSQL 誕生
2006年:Google BigTable
2008年:Facebook Cassandra
2012年:AWS DynamoDB
データの種類や求められる性質が変化してきた。
- データモデル
- ストレージ
- データ構造
- 分散技術
- RDBMSのアーキテクチャ
基本的に書き込む先は一つ、リレーショナルなテーブル形式。
- NoSQLのアーキテクチャ
水平方向の分散、読み書きも分散可能。
保存する型がキーバリューだったりと変わってくる。
- 分散型SQLデータベース ≒ NewSQL のアーキテクチャ
全てに書き込みが可能、リレーショナルなテーブル形式。
コンピュート層とストレージ層の分離、コンピュート層で読み取り/書き込みをルーティング。
2024年のre:Inventで Amazon Aurora DSQLの発表に始まり、日経でも2025年初に分散データベースの特集が組まれており、注目度が高くなっている!
なぜ?
NewSQL(TiDB)では大量の同時接続への対応やオンラインでの水平拡張など、現在業務で必要とされている機能が提供されているから。さらに、スケーラブル、BCP、レジリエンシなどのエンタープライズで必要とされる機能もマネージドで実装されている。
TiDBのアーキテクチャ
※詳細は発表資料を参照ください
TiDBは四つのコンポーネントからできている。
- TiDB(コンピューティング)
- SQL解析(MySQLプロトコルのKV変換)
- Parse、Optimize
- HTAPにおけるクエリ形式判断
- TiKV(ストレージ)
- OLTP用の分散KVS(RocksDB1利用)
- パーティションによる分散データ保持
- Raftで整合性確保
- TiFlash(オプション用ストレージ)
- HTAP2利用時の追加コンポーネント
- OLAP用カラムナストア
- PD:Placement Driver
- データ配置場所の管理
- 分散トランザクションで利用するTSO3の発行
TiDBレイヤ
TiDB上で、アプリケーションから実行されたSQLのParse処理を実施し、AST化4する。
行データをKey-Valueに変換、索引もKey-Valueに変換される。
TiKVレイヤ
TiKVのストレージはRocksDBをベースとしており、データをキーと値のペア(Key-Value)で保存している。
Key-Valueとなるため水平拡張性や高い耐障害性を備えることができる。
また、Raftによる整合性の確保や、LSMツリー5による書き込み性能の確保もこのレイヤーで行われている。
TiDBの利用パターン
TiDBは次の三つのパターンで利用が可能。
- Instance
- TiUPを利用して管理
- Kubernetes6
- TiDB Operatorを利用して管理
- Cloud
- TiDB Cloud、フルマネージド
- Serverless: マルチテナント型
- Dedicated:専有型
- TiDB Cloud、フルマネージド
簡単に始められる TiDB Serverless
- TiDBクラウドはクレカ不要、$0 から利用が可能
- 10秒起動
- MySQLクライアントからも接続情報が自動生成されるため簡単接続が可能
よくある課題と解決策
様々なユースケースで利用されてよくある課題と解決策のノウハウが溜まってきている状況。
-
Writeの観点:PKを散らす
- PKが連番:書き込みホットスポットが発生する場合がある
- PKがランダム:負荷が分散するためホットスポットの回避が可能
-
Readの観点:PKの工夫
- ユーザの情報を時系列に取得したい場合
- サロゲートキー+Index:取得したいデータが分散するため負荷が上がる
- PK:取得したいデータが特定のTiKVに入るため負荷が上がらない
- ユーザの情報を時系列に取得したい場合
-
Readの観点:Covering Index ※PK除いた全カラムのIndex
- 取得したいデータを特定のTiKVノードに収めることでホップ数を削減し高速化
- ストレージが2倍利用される形になる
-
OLTPチューニング
- Read Heavy環境での課題
- TiKVのCPU使用率が上がると全体のレイテンシが低下する
- 内部パラメータ(store-pool-io)の値を変更しリソース効率化
- TiKVのCPU使用率が上がると全体のレイテンシが低下する
- Write Heavy環境における課題
- 多量の履歴データが残るため、検索時に履歴データが含まれた検索となる
- GCで削除の頻度を増やす
- TiKV内にキャッシュを作り最新データのみを読み込む機能(8.4~)
- TiKV内にMVCC7用のインメモリエンジンを搭載し、最新のバージョンをキャッシュ(8.5~)
- 多量の履歴データが残るため、検索時に履歴データが含まれた検索となる
- 多テーブルによる課題
- 統計情報のロードに時間がかかる、インフォメーションスキーマのレスポンスが低下する
- 統計情報のロード性能などの改善
- 統計情報のロードに時間がかかる、インフォメーションスキーマのレスポンスが低下する
- Read Heavy環境での課題
-
移行の高度化
- TiDBのエコツールシステムの利用
- DM(or AWS DMS):フル同期+binlogを利用した差分同期
- Dumpling&Lightning:エクスポートインポート
- ベストプラクティス的な構成も固まってきている
- 移行後のチューニング等も含めて最終的にコストダウンなども視野に
- TiDBのエコツールシステムの利用
セッションまとめ
- TiDBはWrite Heavyな環境にも強い 分散型SQLデータベース(NewSQL)
- TiDB Cloudなどの利用により、TiDBの動作を無料で試してみることも可能
- 金融やゲームなどの様々な環境で利用されるようになってきており、課題に対してのノウハウも溜まってきている
まとめ・感想
まず、今回のレポートではだいぶ省いてますが、セッション資料にはアーキテクチャや内部構造の Dive Deepがありました。他の発表などでもあまり聞けない内容だと思いますので、是非資料をご確認ください。
3週連続でTiDBのお話をレポートしてきましたが、改めて国内でも色々な環境で利用されていることとTiDBの勢いをうかがい知ることができる発表でした。
これからもウォッチしていくのが楽しみですね。
-
RocksDBはFacebook(現Meta)によって開発された高性能な埋め込み型キーバリューストア。書き込み性能に優れているといわれる ↩
-
HTAP(Hybrid Transactional/Analytical Processing:ハイブリッドトランザクション/分析処理)はトランザクション処理(OLTP)と分析処理(OLAP)を単一のデータベースで同時に実行できるデータベースアーキテクチャー ↩
-
タイムスタンプオラクル:分散トランザクションにおいて一貫性を保つために、厳密に増加するタイムスタンプを発行するサービス ↩
-
抽象構文木(AST)はプログラムのソースコードを解析しその構造を木構造で表現したもの。PingCAPはこれらの SQL解析ライブラリ も公開している ↩
-
ログ構造化ツリー:ディスクへの書き込みをシーケンシャルに行うことで、ランダム書き込みに比べて高速な書き込み性能を実現する ↩
-
OSC2025で行われた 「TiDB」をKubernetesで動かしてみよう!2025年最新版 でも解説されていた 【セッションレポート】「”TiDB” をKubernetesで動かしてみよう!2025年最新版」に参加しました ↩
-
MVCC(Multi-Version Concurrency Control:多版同時実行制御)は、データが更新されるたびに古いバージョンを保持し、各トランザクションが開始された時点(厳密にはトランザクション分離レベルによる)での最新のバージョンを参照するというもの。これにより、読み取りトランザクションは書き込みトランザクションを待つことなく、一貫性のあるデータを読み取ることができる ↩