🥭
MongoDBのdropとremoveの使い分け
最近、職場の尊敬する先輩から「MongoDBのdropとremoveは適切に使い分けたほうがいいよ」と教わったので、復習がてらまとめたいと思います。
経緯
あるコレクションのデータが不要になったため、データを全削除したかったです。
今回のケースでは、コレクション自体は削除されてもバッチで再作成されるため、dropでいいだろと思い、dropを実行しました。
その後、シャーディングが有効になってないよ!とslackに通知がきたので、先輩から、そのユースケースならremoveが適してるねと指摘をもらいました。
なぜなのでしょうか。
そもそもなぜシャーディングを有効にするのか
dropとremoveの違いの前に、シャーディングが有効になっていないことのデメリットを書いていきます。
シャーディングを一言でいうと、データを複数のサーバーに分割することです。
そのため、シャーディングが有効になっていないと、一つのサーバーに対して負荷がかかりすぎてしまいます。
では、シャーディングをどう有効にするのかですが、シャードキーと呼ばれるキーをコレクションに設定します。
シャードキーを指定することで、このキーを元にそれぞれのサーバーに格納するデータの範囲を決めていきます。(レンジパーミッション)
dropとremoveの違い
まずdropについてです。
- drop
- 機能
- コレクション自体を削除する
- メリット
- コレクションに関する情報を一挙に削除できる
- デメリット
- インデックスやシャードキーがすべて失われる
- 機能
実際に確認してみます。
- シャーディングが有効になっていることを確認
mongos> db.books.getShardDistribution()
Shard shard0 at shard0/mongodb-shard0:27017
data : 0B docs : 0 chunks : 1
estimated data per chunk : 0B
estimated docs per chunk : 0
Totals
data : 0B docs : 0 chunks : 1
Shard shard0 contains 0% data, 0% docs in cluster, avg obj size on shard : 0B
- データをdropで全削除する
mongos> db.books.drop()
true
- createしてもシャーディングが無効になっていることを確認
mongos> db.createCollection('books')
{
"ok" : 1,
"operationTime" : Timestamp(1660443597, 2),
"$clusterTime" : {
"clusterTime" : Timestamp(1660443597, 2),
"signature" : {
"hash" : BinData(0,"noGpmOZHqGr794jV2dvXtbmb7O4="),
"keyId" : NumberLong("7131545615913189399")
}
}
}
mongos> db.books.getShardDistribution()
Collection test.books is not sharded.
- データベースには旧コレクションのシャーディング情報が残っている
mongos> db.printShardingStatus()
--- Sharding Status ---
sharding version: {
"_id" : 1,
"minCompatibleVersion" : 5,
"currentVersion" : 6,
"clusterId" : ObjectId("62f856f4ad9a27d4a829cf46")
}
shards:
{ "_id" : "shard0", "host" : "shard0/mongodb-shard0:27017", "state" : 1 }
...
databases:
...
{ "_id" : "test", "primary" : "shard0", "partitioned" : true, "version" : { "uuid" : UUID("d720e030-e129-4001-84ab-1ef71dd2d7af"), "lastMod" : 1 } }
removeについてはdropと同様に全ドキュメントを削除することについての記載です。
- remove
- 機能
- ドキュメントを削除する
- メリット
- インデックスやシャードキーを保持したままドキュメントを全削除できる
- デメリット
- 全ドキュメントに対して走査するので効率的ではない
- 機能
これも実際に確認します。
- シャーディングが有効になっていることを確認
mongos> db.books.getShardDistribution()
Shard shard0 at shard0/mongodb-shard0:27017
data : 0B docs : 0 chunks : 1
estimated data per chunk : 0B
estimated docs per chunk : 0
Totals
data : 0B docs : 0 chunks : 1
Shard shard0 contains 0% data, 0% docs in cluster, avg obj size on shard : 0B
- データをremoveで全削除する
mongos> db.books.remove({})
WriteResult({ "nRemoved" : 0 })
- シャーディングが有効になったままなことを確認
mongos> db.books.getShardDistribution()
Shard shard0 at shard0/mongodb-shard0:27017
data : 0B docs : 0 chunks : 1
estimated data per chunk : 0B
estimated docs per chunk : 0
Totals
data : 0B docs : 0 chunks : 1
Shard shard0 contains 0% data, 0% docs in cluster, avg obj size on shard : 0B
まとめ
実際にやってみて、どちらがいいとかはなく、ユースケースに応じて使い分けるべきだと改めて理解できました。
- remove
- データ量が少なくて単純にデータを削除したい場合
- drop
- データ量が多すぎて効率良くデータを削除したい場合
- シャードキーとインデックスを再設定する必要あり
- データ量が多すぎて効率良くデータを削除したい場合
シャーディングはMongoDBにおいて重要な要素なのでしっかり理解していきたいです。
Discussion