Что произойдет, если изменить значение в проиндексированном поле в MongoDB?

Ответ

MongoDB автоматически обновит соответствующие записи во всех индексах, затрагивающих это поле. Это гарантирует консистентность, но имеет последствия для производительности.

Ключевые моменты и пример для Node.js (драйвер mongodb):

  1. Производительность: Каждое обновление индексированного поля приводит к операции записи как в коллекцию, так и в индекс. Частые обновления таких полей могут стать узким местом.

  2. Уникальные индексы: При обновлении на новое значение будет проверяться уникальность.

    const { MongoClient } = require('mongodb');
    const client = new MongoClient(uri);
    await client.connect();
    const collection = client.db('test').collection('users');
    
    // Создаем уникальный индекс по email
    await collection.createIndex({ email: 1 }, { unique: true });
    
    // Это выбросит дубликат ключа ошибку, если 'new@mail.com' уже существует
    await collection.updateOne(
      { _id: userId },
      { $set: { email: 'new@mail.com' } }
    );
  3. Составные индексы: Если поле является частью составного индекса (например, { category: 1, score: -1 }), обновление этого поля приведет к перемещению документа в B-дереве этого составного индекса.

  4. TTL-индексы: Если изменить значение поля, на котором построен TTL-индекс (например, createdAt), таймер удаления документа сбросится, отсчет начнется заново с нового значения.

Рекомендация: Избегайте индексирования полей, значения которых часто обновляются, если это не критично для производительности запросов. Всегда анализируйте профиль запросов (db.collection.explain()) перед созданием индексов.

Ответ 18+ 🔞

Ага, слушай, вот тебе на пальцах про индексы в MongoDB, когда ты там поля меняешь. Представь, что у тебя есть огромная картотека, и ты не просто в карточке что-то исправил, а ещё и во всех алфавитных указателях к ней это исправление нужно внести. Вот MongoDB так и делает — ебушки-воробушки, она за тобой подчищает и в основном хранилище, и во всех индексах, где это поле засветилось. Консистентность, конечно, на высоте, но за это надо платить производительностью, ёпта.

Что важно понять и пример на Node.js (драйвер mongodb):

  1. Производительность: Каждый раз, когда ты лезешь менять проиндексированное поле, это не одна операция записи, а овердохуища. Одна — в саму коллекцию, и по стольку же — в каждый индекс, который это поле использует. Начни часто так делать — и всё, узкое место найдено, сервер будет пыхтеть как паровоз.

  2. Уникальные индексы: Тут вообще отдельная песня. Монго как порядочная система, прежде чем записать новое значение, полезет проверять, а нет ли уже такого. Подставишь несуществующий email — молодец. А если случайно чужой подставишь — получишь по шапке ошибкой дубликата.

    const { MongoClient } = require('mongodb');
    const client = new MongoClient(uri);
    await client.connect();
    const collection = client.db('test').collection('users');
    
    // Вешаем уникальный индекс на почту
    await collection.createIndex({ email: 1 }, { unique: true });
    
    // Если 'new@mail.com' уже есть у кого-то — будет тебе хиросима в виде ошибки дубликата ключа
    await collection.updateOne(
      { _id: userId },
      { $set: { email: 'new@mail.com' } }
    );
  3. Составные индексы: Вот это, блядь, вообще хитрая жопа. Допустим, у тебя индекс по { category: 1, score: -1 }. Ты меняешь score у документа. Так MongoDB не просто строчку в индексе поправит — нет, она возьмёт и переместит всю запись внутри B-дерева этого составного индекса на новое место, потому что порядок изменился. Это дороже, чем кажется.

  4. TTL-индексы: Во, забавная штука. Допустим, есть индекс TTL по полю createdAt, чтобы документы старые сами удалялись. Ты взял и обновил это поле. Что происходит? Старый таймер накрылся медным тазом, и отсчёт времени до удаления начинается заново, уже от нового значения. Документ как бы "омолодился".

Итоговая рекомендация, чувак: Не вешай индексы на поля, которые меняются чаще, чем твоё настроение. Если только без этого нихуя не работает. Прежде чем плодить индексы, всегда включай мозги и смотри db.collection.explain(), что там у тебя с запросами творится. А то наделаешь добра, а потом терпения ноль ебать, пока запросы ползут.