MongoDBのシャーディングとはなにか？図を使って解説

## はじめに
シャーディングとは、データが大量にあるとき、データを複数サーバーに分散させる手法のことです。
MongoDBの設計では、シャーディングを前提として設計することがデザインパターンとされるほど、重要な要素です。

シャーディングを理解する際、横文字が多く、理解しづらい部分ではありますが、この記事では図を使ってわかりやすく解説していきます！

### 備考
本記事では、シャーディングの概要をメインで解説し、実際の設定やデモは別記事に記載します。

## シャーディングとは？

シャーディングは**水平**負荷分散です。
水平にスケーリングするとは、サーバーを追加することです。必要に応じてサーバーを拡張できます。これにより、クエリの作業負荷が分散され、システムの処理能力が向上し、より多くのリクエストに対応できるようになります。

![図1.シャーディングの概要](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1650886/f6c44909-d56a-3d5c-7f75-447ec3c97618.png)

上の図に、シャーディングのイメージを載せています。
APサーバーから「ドキュメント1」がほしいという指令が来た時、どちらのシャードに「ドキュメント1」が配置されているかを判断し、シャード１からデータを取得します。

シャードとは「破片（shard）」という意味で、シャーディングしたデータを格納しているサーバーをシャードサーバーと呼びます。

### シャーディングの利点
シャーディングの利点は、負荷分散によるパフォーマンス向上です。
データを複数サーバに分散させることにより、CPUやI/O負荷を分散させることが可能です。

### チャンクとは？
シャーディングを理解する上でチャンクという概念を知っておく必要があります。
チャンクとはデータの塊を意味し、分割した断片データをサイズで区切り、グループ化したものです。MongoDBはデフォルトで64MBごとに、１チャンクが生成されます。

![スクリーンショット 2023-12-20 21.48.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1650886/bd292481-2a5d-4279-92e4-26294e252d21.png)

シャードの中に複数のチャンクが存在し、さらにそのチャンクの中にグループ化されたドキュメント（データ）が存在します。


### おまけ：パーティションとの違い
シャーディングと似た機能で、パーティションという負荷分散の手法があります。
データを小さく分割するという意味で、シャーディングはパーティションと同じです。
シャーディングは、データを複数サーバーに分散させるのに対し、パーティションは1つのデータベースサーバーに格納するという違いがあります。

## MongoDBにおけるシャーディング
まず、MongoDBにおける、シャーディングの構成を説明します。
MongoDBでシャーディングをするには、シャードサーバーとは別に、mongosとconfigという２つのサーバーが必要です。
mongosとconfigサーバーは、以下のような役割があります。

**mongos**
システムは、mongosに問い合わせを行い、その結果を返します。mongosは軽量プロセスであるため、通常はAPサーバー内に入れます。

**config**
シャーディングの設定を保存しています。どのシャードにどのデータが入っているかを管理しています。mongosから問い合わせを受け、必要なシャード情報を渡してあげます。

![スクリーンショット 2023-12-20 22.07.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1650886/755270fc-89ae-c2a5-b6f4-245981286ca0.png)

#### MongoDBのシャーディングの行われ方
MongoDBではシャーディングは自動で行われます。これをオートバランシングと呼びます。

オートバランシングにより、各シャードサーバーのチャンク数に一定の差がでると、自動でチャンクを空いているシャードサーバーへ移動させます。

![スクリーンショット 2023-12-20 22.19.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1650886/4cd0c5bd-929d-dd19-3c67-c4f7446eb5ae.png)


### シャードキー（ここ重要）
シャードキーはデータを分散する範囲の指標となるキーです。複数指定できます。

シャードキーによって、チャンクがどの範囲で分割されるか決定され、その後、オートバランシングによって各シャードに配置されます。このシャードキーをどのフィールドに設定するかで、パフォーマンスに影響が出るため、シャードキーの設計が非常に重要になります。


例えば、従業員の毎月の給料を管理しているコレクションがあるとします。
従業員IDをシャードキーとすると、次のようにチャンクが分割されます。

| チャンク | **従業員ID（シャードキー）** | 年月      | 給料     |
|----------|----------|-----------|----------|
| 1        | 101      | 2023-01   | ¥300,000 |
| 1        | 101      | 2023-02   | ¥320,000 |
| 1       　　| 101      | 2023-03   | ¥310,000 |
| 2        | 102      | 2023-01   | ¥505,000 |
| 2        | 102      | 2023-02   | ¥525,000 |
| 2        | 102      | 2023-03   | ¥515,000 |
| ...      | ...      | ...       | ...      |

この場合、従業員IDを昇順し、チャンクを分割しています。チャンクの分割は、データのサイズやデータの件数で分割されていきます。


## おわりに
シャーディングについて、図を使って解説しました。


### 参考文献
MongoDB解体新書

https://www.amazon.co.jp/MongoDB-%E8%A7%A3%E4%BD%93%E6%96%B0%E6%9B%B8-%E3%81%93%E3%82%8C%EF%BC%91%E5%86%8A%E3%81%A7%E5%8D%B3%E5%AE%9F%E8%B7%B5%E3%83%AC%E3%83%99%E3%83%AB%EF%BC%81%E7%A9%B6%E6%A5%B5%E3%81%AE%E5%85%A5%E9%96%80%E6%9B%B8-%E7%94%B0%E6%9D%91-%E9%81%94%E4%B9%9F-ebook/dp/B07BGC4MJ1

https://gihyo.jp/dev/serial/01/mongodb/0005#:~:text=%E3%81%A6%E3%81%84%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82-,%E3%82%B7%E3%83%A3%E3%83%BC%E3%83%89%E3%82%AD%E3%83%BC,%E8%87%AA%E5%8B%95%E8%AA%BF%E6%95%B4%E3%82%92%E8%A1%8C%E3%81%84%E3%81%BE%E3%81%99%E3%80%82