NewSQL 2025 - スケーラブルな分散SQLデータベース

2026.01.12

公式ドキュメント

この記事の要点

• NewSQLはACID保証と水平スケーラビリティを両立する次世代データベース
• CockroachDB・TiDB・YugabyteDBなど主要製品が本格的な採用フェーズに
• 金融・Eコマース・グローバルアプリなどユースケース別に最適な選択肢が異なる

NewSQLとは何か

NewSQLは、従来のリレーショナルデータベース(RDBMS)のACID特性と、NoSQLの水平スケーラビリティを両立させた次世代データベースです。2025年、クラウドネイティブアプリケーションの普及により、NewSQLは本格的な採用フェーズに入りました。

なぜNewSQLが必要なのか

従来のアプローチの限界

従来のRDBMS(PostgreSQL、MySQL):

  • ACID保証
  • SQL互換
  • 成熟したエコシステム
  • 垂直スケーリングの限界
  • シャーディングの複雑さ
  • 単一障害点のリスク

NoSQL(MongoDB、Cassandra):

  • 水平スケーリング
  • 高い可用性
  • 柔軟なスキーマ
  • 結果整合性
  • 複雑なクエリの制限
  • トランザクションの制約

NewSQLの解決策

NewSQL:

  • 分散トランザクション(ACID)
  • 自動シャーディング
  • 水平スケーリング
  • 高可用性(自動フェイルオーバー)
  • SQL互換(既存スキルの活用)
  • 地理分散レプリケーション

主要NewSQL製品比較

製品概要

製品開発元ベースDBライセンス特徴
CockroachDBCockroach Labs独自BSL/CommunityPostgreSQL互換、地理分散に強い
TiDBPingCAP独自Apache 2.0MySQL互換、HTAP対応
YugabyteDBYugabytePostgreSQLApache 2.0PostgreSQL完全互換
Google SpannerGoogle独自Proprietaryグローバル分散の元祖
PlanetScalePlanetScaleVitessProprietaryMySQL互換、サーバーレス

パフォーマンス比較(2025年ベンチマーク)

製品TPS(OLTP)レイテンシスケーラビリティ
CockroachDB50,000+2-5ms線形
TiDB100,000+1-3ms線形
YugabyteDB60,000+2-4ms線形
Spanner可変3-10ms無限
PlanetScale30,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からの移行パターン

注意: 従来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_*"

ユースケース

ポイント: NewSQLの選定はユースケースに応じて行いましょう。MySQL互換ならTiDB、PostgreSQL互換ならYugabyteDB/CockroachDB、グローバル分散ならSpannerが有力候補です。

金融サービス

要件:

  • 強い整合性(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 ネイティブ

    • オペレーターの成熟
    • 自動スケーリング
    • マルチクラウド対応

コスト比較(月額概算)

構成CockroachDBTiDB CloudYugabyteDBSpanner
小規模(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

選定ガイド

選定フローチャート

  1. Q1: MySQL互換が必要?

    • Yes → TiDB または PlanetScale
    • No → Q2へ
  2. Q2: PostgreSQL互換が必要?

    • Yes → YugabyteDB または CockroachDB
    • No → Q3へ
  3. Q3: グローバル分散が最優先?

    • Yes → Spanner または CockroachDB
    • No → Q4へ
  4. Q4: OLAPも同時に必要?

    • Yes → TiDB(TiFlash)
    • No → 要件に応じて選択
  5. Q5: サーバーレスが必要?

    • Yes → CockroachDB Serverless / PlanetScale / Neon
    • No → セルフホスト版を検討

実践メモ: 小規模アプリや単一リージョン完結のシステムには従来のRDBMSで十分です。NewSQLの導入は規模と要件に見合う場合に限りましょう。

アンチパターン

避けるべきケース:

  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

参考リソース

この技術を体系的に学びたいですか?

未来学では東証プライム上場企業のITエンジニアが24時間サポート。月額24,800円から、退会金0円のオンラインIT塾です。

メールで無料相談する
← 一覧に戻る