MongoDB C # collection.Save vs Insert + Update - PullRequest
6 голосов
/ 22 ноября 2011

Из документации на C #:

Метод Save представляет собой комбинацию вставки и обновления. Если элемент Id документа имеет значение, то предполагается, что он является существующим документом, и Save вызывает Update для документа (устанавливая флаг Upsert на тот случай, если он действительно является новым документом).

Я создаю свои идентификаторы вручную в базовом классе, от которого наследуются все мои доменные объекты. Поэтому все мои доменные объекты имеют идентификатор, когда они вставляются в MongoDB.

Вопрос в том, должен ли я использовать collection.Save и сохранять свой интерфейс простым или это действительно приводит к некоторым издержкам при вызове Save (с флагом Upsert), и должен ли я вместо этого использовать collection.Insert и Update вместо этого?

Я думаю, что метод Save сначала вызывает Update, а затем выясняет, что мой новый объект вообще не существует, а затем вызывает Insert. Я ошибся? Кто-нибудь проверял это?

Примечание: я вставляю объемные данные с помощью InsertBatch, поэтому большие блоки данных в этом случае не будут иметь значения.

Редактировать, следить

Я написал небольшой тест, чтобы выяснить, были ли вызовы Update с флагом Upsert сопряжены с дополнительными издержками, поэтому вставка могла бы быть лучше. Оказалось, что они бегут с одинаковой скоростью. Смотрите мой тестовый код ниже. MongoDbServer и IMongoDbServer - это мой собственный универсальный интерфейс для изоляции хранилища.

IMongoDbServer server = new MongoDbServer();
Stopwatch sw = new Stopwatch();
long d1 = 0;
long d2 = 0;
for (int w = 0; w <= 100; w++)
{
    sw.Restart();
    for (int i = 0; i <= 10000; i++)
    {
        ProductionArea area = new ProductionArea();
        server.Save(area);
    }
    sw.Stop();
    d1 += sw.ElapsedMilliseconds;
    sw.Restart();
    for (int i = 0; i <= 10000; i++)
    {
        ProductionArea area = new ProductionArea();
        server.Insert(area);
    }
    sw.Stop();
    d2 += sw.ElapsedMilliseconds;
}
long a1 = d1/100;
long a2 = d2/100;

1 Ответ

12 голосов
/ 22 ноября 2011

Метод сохранения - , а не , который собирается совершить две поездки на сервер.

Эвристика такова: если сохраняемый документ не имеет значения для поля _id, то для него создается значение и вызывается Insert. Если сохраняемый документ имеет ненулевое значение для _id, тогда Update вызывается с флагом Upsert, и в этом случае сервер должен решить, делать ли вставку или обновление.

Не знаю, дороже ли Upsert, чем Insert. Я подозреваю, что они почти одинаковы, и что действительно важно, так это то, что в любом случае речь идет об одном круге в одну сеть.

Если вы знаете, что это новый документ, вы можете также позвонить по Insert. И вызов InsertBatch способ более производительный, чем вызов многих отдельных вставок. Поэтому определенно предпочтите InsertBatch для сохранения.

...