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

2026.01.12

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からの移行パターン

移行ステップ

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 ネイティブ
   ・オペレーターの成熟
   ・自動スケーリング
   ・マルチクラウド対応

コスト比較(月額概算)

構成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

選定ガイド

選定フローチャート

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

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

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

LINEで無料相談する
← 一覧に戻る