Azure Cosmos DBってどんなの？

## はじめに

Azure Cosmos DBを今後使っていきそうなので、ちょっとAWSをかじっていたWebエンジニアがキャッチアップのために勉強しつつまとめてみることにしました。

### is 何

- Cosmos DBとは、Azure上で動作するフルマネージドなNoSQLデータベースのPaaSサービスである
- データをJSON形式で作成・閲覧・変更・削除できる。JSON以外の形式にも対応している。
- 短い応答時間、スケーラビリティ、高い可用性、エンプラレベルのセキュリティ、フルマネージドなどあらゆる面で高い性能を誇る

### 他の似たようなやつあるけど、それと比べてどうなの？

- Cosmos DBは、Azureでデータベースを利用する際に検討すべきサービスの第一群
- ある程度の一貫性不足などのリスクが許容できるなら、Cosmos DBを選択することで、最も早く・スケーラブルで・可用性も高いデータベースをコスパよく（使った分だけかかる）用意できるのではないでしょうか
- ただし・・・
    - もし厳密な一貫性を最優先したいならAzure SQL DatabaseなどのRDBMSを検討した方が良いかもしれない
    - もしキャッシュサーバが利用したい場合には、その用途に特化しているAzure Cache for xxx系を検討した方が良いかもしれない
    - もし具体的にPostgreSQLを使いたいとか、AWSやGCPのサービスを使いたいといった場合にはAzure Database for xxx系だったり他のクラウドのサービスだったりを検討した方がよいかもしれない。

### Azure Cosmos DBのリソースの構造

Azure Cosmos DBのリソースの構造は次のようになっています

- Azure Cosmos DBアカウント
    - データベース
        - コンテナー
            - 項目

つまり、「コンテナ」まで作ってようやくデータを入れることができるようになるということですね。

そして、Cosmos DBは「項目」単位でJSONを格納することができる

1項目の例は次の通り

```jsx
{
  "taskId": "task123",
  "title": "CosmosDB プロジェクト計画",
  "description": "CosmosDBを使用したプロジェクトの初期計画を立てる",
  "status": "in_progress",
  "priority": "high",
  "createdDate": "2023-11-01",
  "dueDate": "2023-12-01",
  "subTasks": [
    {
      "subTaskId": "sub1",
      "title": "要件定義",
      "status": "completed",
      "dueDate": "2023-11-10"
    },
    {
      "subTaskId": "sub2",
      "title": "設計書作成",
      "status": "in_progress",
      "dueDate": "2023-11-20"
    }
  ],
  "assignee": {
    "userId": "user456",
    "name": "山田 太郎",
    "email": "yamada@example.com"
  },
  "tags": ["プロジェクト", "CosmosDB", "計画"],
  "comments": [
    {
      "commentId": "comment789",
      "userId": "user123",
      "text": "要件定義のレビュー完了しました。",
      "timestamp": "2023-11-05"
    }
  ]
}
```

さて、このようなデータをどんどん入れていった先に、どのような構造になっているのが望ましいのでしょう？設計時の注意点を考えてみましょう。

## 設計時の注意点

項目を追加していく際、一般的なRDBMSのように、「スキーマが変わると追加できない」といったことがないため、必要がなければ一つのコンテナーに構造が異なる項目をどんどん追加していっても問題ない。

ただ、次のような点で問題が発生する。。

- アクセスパターン：例）特定の1つの項目だけ毎回読み込んでおり、コンテナへの無駄なRU（コンテナ全体のプロビジョニングされたスループット設定の不備）が発生していた
- データのライフサイクル：例）毎日のアプリ動作ログが入っているコンテナに、月別の集計データを入れ、2回目の集計データを計算しようとしたら1回目のデータが邪魔で処理が煩雑になった
- スケーラビリティ：例）ログを配するコンテナにすべてのログを区別せずに入れていたら、ある時を境にアプリログのinfoログが大量に発生し、9割方アプリログばっかりになって実質アプリログ用コンテナになっていたことで、コンテナへの無駄なRUが発生しがちになっていた
- セキュリティポリシー：例）コンテナ単位でアクセス制御をしているが、開発チームと関係がないプラットフォームチームも意図せずデータが見れる状態になっていた

他にも色々考えられるが、共通して言えることは、「ユースケースに合わせた設計にする」ことを追求する必要があるということ。むしろ、ユースケースがみえないうちにコンテナ及びデータベース設計を開始してはいけないとも言える。

## **個人的な推しポイント**

Azure Cosmos DBを使ってみて、特に注目すべきと思ったポイントは次の通りです。

### **マルチモデル対応とグローバルディストリビューション**

- **マルチモデル対応**: Cosmos DBは、ドキュメント、キー-バリュー、グラフ、カラムファミリーなど、多様なデータモデルに対応しています。これにより、さまざまなアプリケーションシナリオに柔軟に対応でき、データモデリングの選択肢が広がります。
- **グローバルディストリビューション**: データのグローバルなレプリケーションを簡単に設定でき、世界中どこでも低レイテンシーでデータにアクセス可能です。特にグローバルに展開するアプリケーションにとって、ユーザーエクスペリエンスの向上に直結します。

### **高度なセキュリティ機能**

- **データの暗号化**: Cosmos DBはデータを自動的に暗号化し、セキュリティの高い環境を提供します。また、Azureのセキュリティセンターとの統合により、より包括的なセキュリティ管理が可能です。
- **ファイングレインドアクセス制御**: エンティティレベルでのアクセス制御により、特定のデータやオペレーションに対して厳密なアクセスポリシーを設定できます。これは、特に機密性の高いデータを扱う場合に重要です。

### **コスト管理のしやすさ**

- RU（**リクエストユニット）による明確な課金**: 使用したリソース量に応じた課金が行われるため、リソースの使用状況に応じてコストを最適化できます。また、オートスケール機能によって、需要に応じて自動的にスループットを調整できるのも大きな利点です。
- **監視と最適化ツール**: Azureの監視ツールを活用することで、リソースの使用状況をリアルタイムで把握し、コストパフォーマンスを常に最適化できます。

## APIの豊富さ

- mongoDBなど、いくつかAPIがあるため、自分が親しんだものがあれば効率よく開発が始められます。

## 最後に

DynamoDBと似たようなもんかな？くらいに思っていましたが、APIが豊富でSQLによる操作的なデータ参照もし易いので、スモールスタートする系の案件が多い自分にとってはすごく魅力的だなと思いました。

## 参考

- はじめに - Azure Cosmos DB | Microsoft Learn https://learn.microsoft.com/ja-jp/azure/cosmos-db/introduction
- Azure Cosmos DB | Microsoft Learn https://learn.microsoft.com/ja-jp/azure/cosmos-db/
- Azure Cosmos DB から Amazon DynamoDB に移行する際に想定される相違点 | Amazon Web Services ブログ https://aws.amazon.com/jp/blogs/news/differences-to-expect-when-migrating-from-azure-cosmos-db-to-amazon-dynamodb/
    - データ構造について高い網羅性があります
- 現実の例を使用したデータをモデル化しパーティション分割する - Azure Cosmos DB for NoSQL | Microsoft Learn https://learn.microsoft.com/ja-jp/azure/cosmos-db/nosql/model-partition-example
    - RUの計算方法などについて詳しく書かれています