NewSQLとは何か
NewSQLは、従来のリレーショナルデータベース(RDBMS)のACID特性と、NoSQLの水平スケーラビリティを両立させた次世代データベースです。2025年、クラウドネイティブアプリケーションの普及により、NewSQLは本格的な採用フェーズに入りました。
なぜNewSQLが必要なのか
従来のアプローチの限界
従来のRDBMS(PostgreSQL、MySQL):
+ ACID保証
+ SQL互換
+ 成熟したエコシステム
- 垂直スケーリングの限界
- シャーディングの複雑さ
- 単一障害点のリスク
NoSQL(MongoDB、Cassandra):
+ 水平スケーリング
+ 高い可用性
+ 柔軟なスキーマ
- 結果整合性
- 複雑なクエリの制限
- トランザクションの制約
NewSQLの解決策
NewSQL:
+ 分散トランザクション(ACID)
+ 自動シャーディング
+ 水平スケーリング
+ 高可用性(自動フェイルオーバー)
+ SQL互換(既存スキルの活用)
+ 地理分散レプリケーション
主要NewSQL製品比較
製品概要
| 製品 | 開発元 | ベースDB | ライセンス | 特徴 |
|---|---|---|---|---|
| CockroachDB | Cockroach Labs | 独自 | BSL/Community | PostgreSQL互換、地理分散に強い |
| TiDB | PingCAP | 独自 | Apache 2.0 | MySQL互換、HTAP対応 |
| YugabyteDB | Yugabyte | PostgreSQL | Apache 2.0 | PostgreSQL完全互換 |
| Google Spanner | 独自 | Proprietary | グローバル分散の元祖 | |
| PlanetScale | PlanetScale | Vitess | Proprietary | MySQL互換、サーバーレス |
パフォーマンス比較(2025年ベンチマーク)
| 製品 | TPS(OLTP) | レイテンシ | スケーラビリティ |
|---|---|---|---|
| CockroachDB | 50,000+ | 2-5ms | 線形 |
| TiDB | 100,000+ | 1-3ms | 線形 |
| YugabyteDB | 60,000+ | 2-4ms | 線形 |
| Spanner | 可変 | 3-10ms | 無限 |
| PlanetScale | 30,000+ | 1-2ms | 線形 |
SQL互換性
-- PostgreSQL互換(CockroachDB、YugabyteDB)
CREATE TABLE orders (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
customer_id INT NOT NULL,
total DECIMAL(10,2),
status VARCHAR(20),
created_at TIMESTAMPTZ DEFAULT now(),
FOREIGN KEY (customer_id) REFERENCES customers(id)
);
-- MySQL互換(TiDB、PlanetScale)
CREATE TABLE orders (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
customer_id INT NOT NULL,
total DECIMAL(10,2),
status VARCHAR(20),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (customer_id) REFERENCES customers(id)
);
アーキテクチャの違い
CockroachDB
┌─────────────────────────────────────────┐
│ CockroachDB Cluster │
├─────────────────────────────────────────┤
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Node 1 │ │ Node 2 │ │ Node 3 │ │
│ │ Range1 │ │ Range1 │ │ Range2 │ │
│ │ Range3 │ │ Range2 │ │ Range3 │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ ・Raft合意による強整合性 │
│ ・Range(64MB単位)による自動シャーディング│
│ ・レプリカ数は設定可能(デフォルト3) │
└─────────────────────────────────────────┘
TiDB
┌─────────────────────────────────────────┐
│ TiDB Architecture │
├─────────────────────────────────────────┤
│ ┌──────────────────┐ │
│ │ TiDB Server │ SQLレイヤー │
│ │ (ステートレス)│ │
│ └────────┬─────────┘ │
│ │ │
│ ┌──────────────┼──────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌────┐ ┌────┐ ┌────┐ │
│ │TiKV│ │TiKV│ │TiKV│ 分散KV │
│ └────┘ └────┘ └────┘ │
│ │
│ ┌────────────────────────────────┐ │
│ │ PD Cluster │ 管理 │
│ └────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────┐ │
│ │ TiFlash │ OLAP │
│ └────────────────────────────────┘ │
└─────────────────────────────────────────┘
実践的なコード例
CockroachDBでのアプリケーション開発
// Node.js + CockroachDB
import { Pool } from 'pg';
const pool = new Pool({
connectionString: 'postgresql://root@localhost:26257/defaultdb?sslmode=disable',
max: 20
});
// 分散トランザクション
async function transferFunds(fromAccount, toAccount, amount) {
const client = await pool.connect();
try {
await client.query('BEGIN');
// 送金元の残高確認と更新
const { rows: [sender] } = await client.query(
'SELECT balance FROM accounts WHERE id = $1 FOR UPDATE',
[fromAccount]
);
if (sender.balance < amount) {
throw new Error('Insufficient funds');
}
await client.query(
'UPDATE accounts SET balance = balance - $1 WHERE id = $2',
[amount, fromAccount]
);
// 送金先の残高更新
await client.query(
'UPDATE accounts SET balance = balance + $1 WHERE id = $2',
[amount, toAccount]
);
await client.query('COMMIT');
return { success: true };
} catch (error) {
await client.query('ROLLBACK');
throw error;
} finally {
client.release();
}
}
TiDBでのHTAP処理
# Python + TiDB(リアルタイム分析)
import mysql.connector
from mysql.connector import pooling
# コネクションプール設定
config = {
"pool_name": "tidb_pool",
"pool_size": 10,
"host": "tidb.example.com",
"port": 4000,
"user": "root",
"password": "password",
"database": "analytics"
}
pool = mysql.connector.pooling.MySQLConnectionPool(**config)
def realtime_analytics():
"""
TiFlashを使用したリアルタイム分析
OLTPとOLAPを同時に処理
"""
conn = pool.get_connection()
cursor = conn.cursor(dictionary=True)
try:
# TiFlashへのヒントでカラム指向ストレージを使用
cursor.execute("""
SELECT /*+ READ_FROM_STORAGE(tiflash[orders]) */
DATE(created_at) as date,
COUNT(*) as order_count,
SUM(total) as revenue,
AVG(total) as avg_order_value
FROM orders
WHERE created_at >= NOW() - INTERVAL 7 DAY
GROUP BY DATE(created_at)
ORDER BY date DESC
""")
return cursor.fetchall()
finally:
cursor.close()
conn.close()
def insert_order(order_data):
"""
TiKVへの高速書き込み(OLTP)
"""
conn = pool.get_connection()
cursor = conn.cursor()
try:
cursor.execute("""
INSERT INTO orders (customer_id, total, status)
VALUES (%s, %s, %s)
""", (order_data['customer_id'], order_data['total'], 'pending'))
conn.commit()
return cursor.lastrowid
finally:
cursor.close()
conn.close()
YugabyteDBでの地理分散
-- YugabyteDB: リージョンごとのテーブル配置
-- 日本リージョンにデータを配置
CREATE TABLESPACE japan_tablespace WITH (
replica_placement='{"num_replicas": 3, "placement_blocks": [
{"cloud": "aws", "region": "ap-northeast-1", "zone": "ap-northeast-1a", "min_num_replicas": 1},
{"cloud": "aws", "region": "ap-northeast-1", "zone": "ap-northeast-1c", "min_num_replicas": 1},
{"cloud": "aws", "region": "ap-northeast-1", "zone": "ap-northeast-1d", "min_num_replicas": 1}
]}'
);
-- 日本ユーザーのデータを日本リージョンに配置
CREATE TABLE japan_users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) UNIQUE NOT NULL,
name VARCHAR(100),
created_at TIMESTAMPTZ DEFAULT now()
) TABLESPACE japan_tablespace;
-- グローバルテーブル(全リージョンにレプリケート)
CREATE TABLE global_config (
key VARCHAR(100) PRIMARY KEY,
value JSONB,
updated_at TIMESTAMPTZ DEFAULT now()
) WITH (
colocation = false
) SPLIT INTO 1 TABLETS;
Go言語での接続例
// Go + CockroachDB
package main
import (
"context"
"log"
"time"
"github.com/jackc/pgx/v5/pgxpool"
)
type Order struct {
ID string
CustomerID int
Total float64
Status string
CreatedAt time.Time
}
func main() {
ctx := context.Background()
// コネクションプール設定
config, err := pgxpool.ParseConfig(
"postgresql://root@localhost:26257/defaultdb?sslmode=disable",
)
if err != nil {
log.Fatal(err)
}
config.MaxConns = 25
config.MinConns = 5
config.MaxConnLifetime = time.Hour
pool, err := pgxpool.NewWithConfig(ctx, config)
if err != nil {
log.Fatal(err)
}
defer pool.Close()
// バッチインサート
if err := batchInsertOrders(ctx, pool); err != nil {
log.Fatal(err)
}
}
func batchInsertOrders(ctx context.Context, pool *pgxpool.Pool) error {
batch := &pgx.Batch{}
for i := 0; i < 1000; i++ {
batch.Queue(
"INSERT INTO orders (customer_id, total, status) VALUES ($1, $2, $3)",
i%100,
float64(i)*10.5,
"pending",
)
}
br := pool.SendBatch(ctx, batch)
defer br.Close()
for i := 0; i < batch.Len(); i++ {
if _, err := br.Exec(); err != nil {
return err
}
}
return nil
}
従来RDBMSからの移行パターン
移行ステップ
Phase 1: 評価と準備(2-4週間)
├── ワークロード分析
├── 互換性チェック
├── パフォーマンステスト
└── 移行計画策定
Phase 2: スキーマ移行(1-2週間)
├── DDL変換
├── インデックス最適化
├── パーティショニング設計
└── テストデータ投入
Phase 3: データ移行(規模による)
├── 初期データ同期
├── CDC(Change Data Capture)設定
├── 差分同期
└── 整合性検証
Phase 4: アプリケーション移行(2-4週間)
├── 接続文字列変更
├── クエリ最適化
├── リトライロジック追加
└── パフォーマンスチューニング
Phase 5: カットオーバー(1日)
├── 書き込み停止
├── 最終同期
├── DNS切り替え
└── 監視強化
PostgreSQLからCockroachDBへの移行
# 1. スキーマのエクスポート
pg_dump --schema-only -d mydb > schema.sql
# 2. 非互換構文の修正
# - SERIAL → INT DEFAULT unique_rowid()
# - 一部のインデックスタイプ
# - 特定の拡張機能
# 3. CockroachDBへのインポート
cockroach sql --insecure < schema.sql
# 4. データ移行(IMPORT INTO使用)
cockroach sql --insecure -e "
IMPORT INTO users (id, name, email, created_at)
CSV DATA ('s3://bucket/users.csv?AWS_ACCESS_KEY_ID=...&AWS_SECRET_ACCESS_KEY=...')
WITH skip = '1';
"
MySQLからTiDBへの移行
# TiDB Data Migration (DM) 設定
source-config:
source-id: "mysql-replica-01"
from:
host: "mysql.example.com"
port: 3306
user: "dm_user"
password: "password"
task:
name: "mysql-to-tidb"
task-mode: "all" # full + incremental
target-database:
host: "tidb.example.com"
port: 4000
user: "root"
password: ""
mysql-instances:
- source-id: "mysql-replica-01"
block-allow-list: "balist"
block-allow-list:
balist:
do-dbs: ["production_db"]
ignore-tables:
- db-name: "production_db"
tbl-name: "temporary_*"
ユースケース
金融サービス
要件:
・強い整合性(ACIDトランザクション)
・高可用性(99.999%)
・地理分散(規制対応)
・監査ログ
推奨: CockroachDB または Spanner
理由: 地理分散トランザクション、強整合性
Eコマース
要件:
・高スループット(注文処理)
・リアルタイム分析
・セール時のスパイク対応
・コスト効率
推奨: TiDB
理由: HTAP対応、MySQL互換、スケーラビリティ
SaaS/マルチテナント
要件:
・テナント分離
・スキーマ進化
・開発者体験
・PostgreSQL互換
推奨: YugabyteDB または CockroachDB
理由: PostgreSQL完全互換、Kubernetes親和性
グローバルアプリケーション
要件:
・世界中からの低レイテンシアクセス
・データレジデンシー対応
・障害時の自動フェイルオーバー
推奨: Google Spanner または CockroachDB
理由: グローバル分散、TrueTime/HLC
2025年の動向
市場トレンド
1. サーバーレスNewSQLの台頭
・CockroachDB Serverless
・PlanetScale
・Neon(PostgreSQL)
2. エッジコンピューティング対応
・軽量なエッジノード
・部分的なデータ同期
・オフライン対応
3. AIワークロード統合
・ベクトル検索のサポート
・MLパイプライン統合
・インデータベースML
4. Kubernetes ネイティブ
・オペレーターの成熟
・自動スケーリング
・マルチクラウド対応
コスト比較(月額概算)
| 構成 | CockroachDB | TiDB Cloud | YugabyteDB | Spanner |
|---|---|---|---|---|
| 小規模(3ノード) | $500-1,000 | $400-800 | $500-900 | $1,500+ |
| 中規模(9ノード) | $3,000-5,000 | $2,500-4,000 | $3,000-4,500 | $5,000+ |
| 大規模(27ノード+) | $15,000+ | $12,000+ | $14,000+ | $20,000+ |
採用企業
CockroachDB:
・Netflix、DoorDash、Bose、Lush
TiDB:
・Square、PayPay、Shopee、BookMyShow
YugabyteDB:
・Kroger、Narvar、Yugabyte自体
Spanner:
・Spotify、Twitter、Snap
選定ガイド
選定フローチャート
Q1: MySQL互換が必要?
Yes → TiDB または PlanetScale
No → Q2へ
Q2: PostgreSQL互換が必要?
Yes → YugabyteDB または CockroachDB
No → Q3へ
Q3: グローバル分散が最優先?
Yes → Spanner または CockroachDB
No → Q4へ
Q4: OLAPも同時に必要?
Yes → TiDB(TiFlash)
No → 要件に応じて選択
Q5: サーバーレスが必要?
Yes → CockroachDB Serverless / PlanetScale / Neon
No → セルフホスト版を検討
アンチパターン
避けるべきケース:
1. 小規模アプリケーション
→ PostgreSQL/MySQLで十分
2. 単一リージョンで完結
→ 従来RDBMSの方がシンプル
3. 予算が限られている
→ オープンソースRDBMS + Read Replica
4. 複雑なストアドプロシージャ依存
→ NewSQLでは制限がある場合も
Kubernetes上でのデプロイ
CockroachDB Operator
# CockroachDB on Kubernetes
apiVersion: crdb.cockroachlabs.com/v1alpha1
kind: CrdbCluster
metadata:
name: cockroachdb
spec:
dataStore:
pvc:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: "100Gi"
volumeMode: Filesystem
resources:
requests:
cpu: "4"
memory: "16Gi"
limits:
cpu: "8"
memory: "32Gi"
tlsEnabled: true
image:
name: cockroachdb/cockroach:v23.2.0
nodes: 3
additionalLabels:
app: cockroachdb
TiDB Operator
# TiDB on Kubernetes
apiVersion: pingcap.com/v1alpha1
kind: TidbCluster
metadata:
name: tidb-cluster
spec:
version: v7.5.0
timezone: Asia/Tokyo
pd:
replicas: 3
requests:
storage: "10Gi"
config: {}
tikv:
replicas: 3
requests:
storage: "100Gi"
config: {}
tidb:
replicas: 2
service:
type: LoadBalancer
config: {}
tiflash:
replicas: 2
storageClaims:
- resources:
requests:
storage: "100Gi"
モニタリングとオブザーバビリティ
# Prometheus + Grafana 設定
scrape_configs:
- job_name: 'cockroachdb'
static_configs:
- targets: ['cockroachdb-0:8080', 'cockroachdb-1:8080', 'cockroachdb-2:8080']
metrics_path: '/_status/vars'
- job_name: 'tidb'
static_configs:
- targets: ['tidb-0:10080', 'tidb-1:10080']
# 重要メトリクス
key_metrics:
- name: sql_query_latency_p99
threshold: 100ms
alert: critical
- name: range_replication_lag
threshold: 10s
alert: warning
- name: storage_capacity_used_percent
threshold: 80%
alert: warning
まとめ
2025年、NewSQLは概念実証から本番環境へと成熟しました。ACID保証と水平スケーラビリティの両立は、もはや夢ではなく現実です。CockroachDB、TiDB、YugabyteDBなどの製品は、それぞれ異なる強みを持ち、ユースケースに応じた選択が重要です。
従来のRDBMSからの移行は慎重に計画する必要がありますが、クラウドネイティブ時代において、NewSQLはデータベースの新しいスタンダードとなりつつあります。特に、グローバル展開、高可用性、リアルタイム分析が求められるアプリケーションでは、NewSQLの採用を積極的に検討すべきでしょう。
← 一覧に戻る参考: CockroachDB Documentation, TiDB Documentation, YugabyteDB Documentation