Подтвердить что ты не робот

Должен ли я выполнять автоматическое увеличение в MongoDB?

Я перехожу к MongoDB из MySQL. Знакомая архитектура для очень простой таблицы users имела бы автоматическое приращение uid. См. собственную документацию Mongo для этого варианта использования.

Мне интересно, это лучшее архитектурное решение. С точки зрения UX мне нравится иметь UID как внешние ссылки, например, в более коротких URL-адресах: http://example.com/users/12345

Есть ли третий способ? Кто-то из IRC Freenode #mongodb предложил создать ряд идентификаторов и кэшировать их. Я не знаю, как это реализовать, или есть ли еще один маршрут, на который я могу пойти. Мне не обязательно даже нужно, чтобы _id сам увеличивался таким образом. Пока users все имеют уникальный номер uid в документе, я был бы счастлив.

4b9b3361

Ответ 1

Джош, В MongoDB нет идентификатора автоинкремента, и есть веские причины. Я бы сказал, идут с ObjectIds, которые уникальны в кластере.

Вы можете добавить автоматический инкремент с помощью коллекции последовательностей и с помощью findAndModify, чтобы получить следующий идентификатор. Это определенно добавит сложности вашему приложению и может также повлиять на возможность очертить вашу базу данных.

Пока вы можете гарантировать, что созданные вами идентификаторы будут уникальными, вы будете в порядке. Но головная боль будет там.

Вы можете посмотреть эту запись для получения дополнительной информации об этом вопросе в выделенной группе google для MongoDB:

http://groups.google.com/group/mongodb-user/browse_thread/thread/f57b712b2aae6f0b/b4315285e689b9a7?lnk=gst&q=projapati#b4315285e689b9a7

Надеюсь, что это поможет.

Спасибо

Ответ 2

Я категорически не согласен с автором выбранного ответа: "Нет auto-increment id в MongoDB и есть веские причины. Мы не знаем причин, почему 10gen не поощрял использование автоматически увеличивающихся идентификаторов. Это спекуляция. Я думаю, что 10gen сделал этот выбор, потому что просто проще обеспечить уникальность 12-байтных идентификаторов в кластерной среде. Это решение по умолчанию, которое подходит большинству новичков, поэтому увеличивает принятие продукта, что хорошо для бизнеса 10gen.

Теперь позвольте мне рассказать всем о моем опыте с ObjectIds в коммерческой среде.

Я строю социальную сеть. У нас примерно 6M пользователей, и у каждого пользователя около 20 друзей.

Теперь представьте, что у нас есть коллекция, в которой хранятся отношения между пользователями (кто следует за кем). Похоже на это

_id : ObjectId
user_id : ObjectId
followee_id : ObjectId

на котором у нас есть уникальный составной индекс {user_id, followee_id}. Мы можем оценить размер этого индекса как 12 * 2 * 6M * 20 = 2 ГБ. Теперь этот индекс для быстрого поиска людей я следую. Для быстрого поиска людей, которые следуют за мной, мне нужен обратный индекс. Это еще 2 ГБ.

И это только начало. Я должен носить эти идентификаторы повсюду. У нас есть кластер активности, где мы храним вашу ленту новостей. Это каждое событие, которое вы или ваши друзья делаете. Представьте, сколько места занимает.

И, наконец, один из наших инженеров принял бессознательное решение и решил хранить ссылки как строки, которые представляют ObjectId, который удваивает его размер.

Что произойдет, если индекс не вписывается в ОЗУ? Ничего хорошего, говорит 10gen:

Когда индекс слишком велик для размещения в ОЗУ, MongoDB должен прочитать индекс с диска, что намного медленнее, чем чтение из ОЗУ. Имейте в виду, что индекс вписывается в ОЗУ, когда на вашем сервере имеется ОЗУ для индекса в сочетании с остальной частью рабочего набора.

Это означает, что чтение выполняется медленно. Конфликт замков увеличивается. Записи также замедляются. Увидев конфликт блокировки на 80% -nish больше не шокирует меня.

Прежде чем вы это узнаете, вы столкнулись с кластером 460 ГБ, который вам нужно разделить на осколки и с которым довольно сложно манипулировать.

Facebook использует 64-битный длинный идентификатор пользователя:) Есть причина для этого. Вы можете генерировать последовательные идентификаторы

  • используя 10gen advice.
  • используя mysql в качестве хранилища счетчиков (если вы беспокоитесь о скорости, посмотрите handlersocket)
  • используя службу генерации идентификаторов, которую вы создали, или используя что-то вроде Snowflake через Twitter.

Итак, вот мой общий совет для всех. Пожалуйста, сделайте свои данные как можно меньшими. Когда вы вырастите это, вы сэкономите много бессонных ночей.

Ответ 3

Итак, существует фундаментальная проблема с идентификаторами "auto-increment". Когда у вас есть 10 разных серверов (осколки в MongoDB), кто выбирает следующий идентификатор?

Если вам нужен один набор автоинкрементных идентификаторов, у вас должен быть единый орган для выбора этих идентификаторов. В MySQL это, как правило, довольно просто, поскольку у вас только один сервер, принимающий записи. Но большие развертывания MongoDB запускают осколки, у которых нет этой "центральной власти".

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

Итак, вот большой вопрос: "Можете ли вы позволить себе иметь единую власть"?

Если да, тогда вы можете использовать findAndModify для отслеживания "последнего наивысшего идентификатора", а затем вы можете вставить с ним.

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

Ответ 4

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

Ответ 5

По умолчанию Mongo ObjectId - тот, который используется в поле _id - увеличивается.

Mongo использует временную метку (секунды с эпохи Unix) в качестве первой 4-байтовой части ее композиции 4-3-2-3, очень похожей (если не совсем) той же композиции, что и UUID Версии 1. И этот ObjectId генерируется во время вставки (если другой пользователь не поддерживает другой тип _id)

Таким образом, ObjectId является порядковым по своей природе; кроме того, сортировка по умолчанию основана на этой инкрементной метке времени.

Можно рассматривать его как обновленную версию идентификаторов автоматического инкремента (index ++), используемых во многих dbms.