MongoDB и составные первичные ключи

Я пытаюсь определить лучший способ справиться с составным первичным ключом в Mongo db. Основной ключ для взаимодействия с данными в этой системе состоит из 2 UUID. Сочетание uuids гарантированно будет уникальным, но ни один из отдельных uuids не является.

Я вижу несколько способов управления этим:

  1. использовать объект для первичного ключа, который состоит из 2 значений (как предложил здесь)

  2. используйте стандартный автоматически сгенерированный идентификатор объекта mongo в качестве первичного ключа, сохраните мой ключ в двух отдельных полях, а затем создайте составной индекс на этих двух полях

  3. сделайте первичный ключ хэшем из 2 UUID

  4. какое-то другое удивительное решение, о котором я в настоящее время не знаю

каковы последствия этих подходов для производительности?

для Вариант 1, я беспокоюсь о производительности вставки из-за наличия не последовательных ключей. Я знаю, что это может убить традиционные системы РСУБД, и я видел признаки того, что это может быть верно и в MongoDB.

для варианта 2 кажется немного странным иметь первичный ключ, который никогда не будет использоваться системой. Кроме того, кажется, что производительность запросов может быть не такой хорошей, как в варианте 1. В традиционной СУБД кластеризованный индекс дает лучшие результаты запроса. Насколько это актуально в В MongoDB?

для варианта 3 это создаст одно поле id, но опять же оно не будет последовательным при вставке. Есть ли другие плюсы/минусы этого подхода?

для варианта 4, хорошо... какой вариант 4?

кроме того, есть некоторое обсуждение возможности использования CouchDB вместо MongoDB в какой-то момент в будущем. Будет ли использование CouchDB предлагать другое решение?

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ: некоторые предпосылки о проблеме могут быть найдено здесь

4 ответов


вы должны пойти с вариантом 1.

основная причина в том, что вы говорите, что беспокоитесь о производительности - использование индекса _id, который всегда есть и уже уникален, позволит вам сэкономить на поддержании второго уникального индекса.

для варианта 1 я беспокоюсь о производительности вставки, чтобы иметь не последовательные ключи. Я знаю, что это может убить традиционные системы РСУБД и я видел признаки того, что это может быть правдой в MongoDB как что ж.

ваши другие параметры не избегают этой проблемы, они просто переносят ее из индекса _id во вторичный уникальный индекс - но теперь у вас есть два индекса, как только это правильно сбалансировано, а другой-случайный доступ.

существует только одна причина для вопроса Вариант 1, и это если вы планируете получить доступ к документам только одним или только другим значением UUID. Пока вы всегда предоставляете оба значения и (эта часть очень важна) вы всегда заказываете их одинаково во всех ваших запросах, тогда индекс _id будет эффективно служить своему полному назначению.

в качестве уточнения, почему вы должны убедиться, что вы всегда заказываете два значения UUID одинаково, при сравнении поддокументов { a:1, b:2 } не равно { b:2, a:1 } - у вас может быть коллекция, в которой два документа имели эти значения для _id. Поэтому, если вы сначала храните _id с полем a, вы всегда должны сохранять этот порядок во всех своих документах и запросах.

в другое предостережение-это индекс на _id:1 будет использоваться для запроса:

db.collection.find({_id:{a:1,b:2}}) 

но это не можно использовать для запроса

db.collection.find({"_id.a":1, "_id.b":2})

у меня есть вариант 4 для вас:

использовать автоматическую _id field и добавьте 2 одиночных индекса поля для обоих uuid вместо одного составного индекса.

  1. на _id индекс будет последовательным (хотя это менее важно в MongoDB), легко сегментируемые, и вы можете позволить MongoDB управлять ею.
  2. индексы 2 uuid позволяют вам сделать любой запрос, который вам нужен (с первым, со вторым или с обоими в любом порядке), и они занимают меньше космоса чем 1 составной индекс.
  3. если вы используете оба индекса (и другие) в одном запросе MongoDB будет пересечение их (новое в v2.6) как если бы вы использовали составной индекс.

Я ЗА 2 вариант и вот почему

  1. наличие двух отдельных полей вместо одного, объединенного с обоими UUID, как предложено в 1st, оставит вам возможность создавать другие комбинации индексов для поддержки будущих запросов запросов или, если окажется, что мощность одного ключа выше, чем другой.
  2. имеющие номера последовательных ключей может помочь вам избежать горячих точек при вставке в сегментированной среде, поэтому его не такая уж и плохая выбор. Sharding-лучший способ, на мой взгляд, масштабировать вставки и обновления в коллекциях, поскольку блокировка записи находится на уровне базы данных (до 2.6) или на уровне коллекции (версия 2.6)

Я бы пошел с вариантом 2. Вы все равно можете сделать индекс, который обрабатывает оба поля UUID, и производительность должна быть такой же, как составной первичный ключ, за исключением того, что с ним будет намного проще работать.

кроме того, по моему опыту, я никогда не жалел, что дал что-то уникальное удостоверение личности, даже если это не было строго необходимо. Возможно, это непопулярное мнение.