📘

Azure Table Storage を使ってみた

に公開

はじめに

私が参画しているとあるプロジェクトで、Blob Storage に CSV ファイルを置いてデータを管理していましたが、1 件のデータ取得や更新でもファイル全体を読み書きする必要があり、メタデータやタグを使って頑張っていましたが、機能数が増えるにつれ非効率さが問題になってきたので、別の方法を模索していました。

そこで、Azure Table Storage を試してみたので、本記事では、実際に使ってみてわかったことをまとめます。

  • Azure Table Storage の基本的な使い方
  • RDB や Cosmos DB との違い
  • 実際に使ってわかった向き不向き

Azure Table Storage とは

Azure が提供する NoSQL 型の Key-Value ストアです。

特徴

  • 個別レコード単位で CRUD 操作
  • PartitionKey + RowKey でデータを管理
  • 低コスト(月額数十円〜)
  • スキーマレス

Python + FastAPI で CRUD API を実装してみる

環境構築

uv init
uv add azure-data-tables

# .env
AZURE_STORAGE_CONNECTION_STRING=<接続文字列>
TABLE_NAME=users

実装例

from azure.data.tables import TableServiceClient
from azure.core.exceptions import ResourceNotFoundError
import uuid

# クライアント接続
table_service = TableServiceClient.from_connection_string(CONNECTION_STRING)
table_client = table_service.get_table_client(TABLE_NAME)

# CREATE - データ作成
entity = {
    "PartitionKey": "users",
    "RowKey": str(uuid.uuid4()),
    "name": "山田太郎",
    "email": "yamada@example.com"
}
table_client.create_entity(entity)

# READ - データ取得
entity = table_client.get_entity(
    partition_key="users",
    row_key="user_id_123"
)

# UPDATE - データ更新
entity["name"] = "山田花子"
table_client.update_entity(entity)

# DELETE - データ削除
table_client.delete_entity(
    partition_key="users",
    row_key="user_id_123"
)

# QUERY - 条件検索
query_filter = "age ge 30"
entities = table_client.query_entities(query_filter=query_filter)

PartitionKey と RowKey

PartitionKey + RowKey を 複合主キーとしてデータを一意に識別します。

entity = {
    "PartitionKey": "users",  # データのグループ
    "RowKey": "user123",      # 個別のID
    "name": "山田太郎"
}
  • RowKey はパーティション内で一意(テーブル全体ではない)
  • 検索性能
    • PartitionKey + RowKey を指定(O(1))→ 最速
    • PartitionKey のみ(パーティションスキャン)→ 遅い
    • 他のフィールドで検索(フルスキャン)→ 非常に遅い

RDB との違い

機能 Table Storage 備考
JOIN ❌ 不可 アプリ側で手動結合が必要
部分一致検索 ❌ 不可(LIKE) 全件取得してフィルタリング
集計関数 ❌ 不可(SUM, AVG, COUNT 等) アプリ側で計算
サブクエリ ❌ 不可 -
比較演算 ✅ 可(eq, ge, le, gt, lt) 複数条件も可(and, or)
完全一致検索 ✅ 可 -
トランザクション ⚠️ 同一パーティション内のみ(最大 100 件) -

パーティション設計の重要性

PartitionKey の設計は性能に直結します。

パターン 向いているケース 注意点
固定 "users" (すべて同じ) 小〜中規模 (〜10 万件) 大規模だとスケールしない
ハッシュ分散 "users_00""users_99" 大規模 (100 万件〜) 全体検索が遅くなる
意味のある分割 日付 "2025-01-05", リージョン よく使う条件で高速検索可能 設計が重要(後から変更困難)

バッチトランザクション(一括更新)は同一 PartitionKey 内のみ可能(最大 100 件)。異なるパーティション間では個別に操作する必要があります。

使ってみてわかったこと

向いているケース

  1. シンプルな Key-Value 検索

    • ユーザー ID → ユーザー情報
    • セッション ID → セッションデータ
  2. 時系列データ・ログ

    • 日付ごとにパーティション分割
    • 古いデータの一括削除が容易
  3. カテゴリーがはっきりしているデータ

    • 商品カテゴリー別の商品マスター
    • リージョン別のユーザーデータ
  4. 大量データを低コストで保存

    • 複雑な検索は不要
    • 単純な条件での絞り込みのみ

向いていないケース

  1. 複雑な検索が必要

    • JOIN、サブクエリ、複雑な条件
    • → Azure SQL Database、Cosmos DB
  2. 部分一致検索が多い

    • 全文検索、あいまい検索
    • → Azure Cognitive Search、Elasticsearch
  3. トランザクション整合性が重要

    • 複数テーブル間の整合性
    • → Azure SQL Database
  4. 頻繁にスキーマが変わる

    • リレーションシップが複雑
    • → RDB

Cosmos DB との違い

Cosmos DB の Table API も使えるのでは? と思うかもしれませんが、料金が全く違います。

料金比較(月間)

1GB のデータ、月間 100 万トランザクション の想定

項目 Table Storage Cosmos DB (Table API)
ストレージ $0.05 $0.28
トランザクション $0.04 約$24〜
合計 $0.09 $24〜

Cosmos DB は最低でも 400 RU/s(約$24/月)からなので、小規模なら Table Storage の方が圧倒的に安いです。

機能比較

機能 Table Storage Cosmos DB
グローバル分散 ✅ 世界中にレプリケーション
SLA 99.9% 99.999%
レイテンシ保証 ベストエフォート 1 桁ミリ秒保証
高度なクエリ ✅ SQL, MongoDB, Cassandra 等
自動スケーリング 限定的 ✅ 柔軟
コスト ✅ 非常に安い 高い

使い分け

  • Table Storage: コスト重視、シンプルな用途、小〜中規模
  • Cosmos DB: グローバル展開、ミッションクリティカル、高度な機能が必要

PoC や小規模アプリでは Table Storage を選び、将来的にスケールが必要なら Cosmos DB に移行するのもありだと思います。

まとめ

Table Storage が適してそうな場合

  1. 個別レコードの CRUD が主な操作
    • → Blob Storage (CSV) より圧倒的に効率的
  2. 検索条件がシンプル(PartitionKey + RowKey、比較演算のみ)
    • → RDB ほどの複雑な機能は不要
  3. コストを抑えたい(月額数十円〜数百円)
    • → Cosmos DB の数百分の一のコスト
  4. 小〜中規模のデータ(〜数百万件)
    • → 大規模ならパーティション設計が複雑化

具体例

  • ユーザー情報の管理(ID → ユーザーデータ)
  • セッションデータの保存
  • 日次ログの蓄積
  • 商品マスターデータ(カテゴリ別)

別の選択肢を使うべき場合

こんな時は 使うべきサービス 理由
JOIN が必要 Azure SQL Table Storage は JOIN 不可
部分一致検索が必要 Azure SQL LIKE 検索できない
グローバル展開 Cosmos DB Table Storage は単一リージョン
超低レイテンシ必須 Cosmos DB Table Storage はベストエフォート
ファイル保存 Blob Storage Table Storage は構造化データ向け

おわりに

システム設計の一助となれば幸いです。

参考

NCDCエンジニアブログ

Discussion