Точка уникальности значения Cosmos DB только для каждого ключа сегмента (ключа раздела)

#mongodb #azure-cosmosdb #sharding #uniqueidentifier #azure-cosmosdb-mongoapi

#mongodb #azure-cosmosdb #сегментирование #uniqueidentifier #azure-cosmosdb-mongoapi

Вопрос:

Документация Microsoft по управлению индексацией в API Azure Cosmos DB для MongoDB гласит, что:

API Azure Cosmos DB для сервера MongoDB версии 3.6 автоматически индексирует поле _id, которое нельзя удалить. Он автоматически обеспечивает уникальность поля _id для каждого ключа сегмента.

Я смущен рассуждениями о части «для каждого ключа сегмента«. Я вижу это как «ваше уникальное поле вообще не будет уникальным в глобальном масштабе», потому что, если я правильно понимаю, если у меня есть поле Guid _id как уникальное, а userId поле — как ключ раздела, тогда у меня может быть 2 элемента с одинаковым идентификатором при условии, что они принадлежат 2 разным пользователям.

Может быть, я не могу выбрать правильный ключ раздела? Потому что, в моем понимании, ключом раздела должно быть поле, которое наиболее часто используется для фильтрации данных. Но что, если мне нужно выбрать данные из базы данных только по значению поля ID? Или запрашивать данные для всех пользователей?

Это неотъемлемые ограничения в распределенных системах, которые мне нужно принять и, следовательно, перестроить мой процесс проектирования базы данных и программирования доступа к ней? Что в этом случае было бы: ВСЕГДА запрашивать ваши данные из этой коллекции не только по _id полю, но сначала по userId полю? И не рассматривать только мое _id поле как идентификатор, а скорее рассматривать идентификатор как соединение userId и _id ?

Комментарии:

1. Если ваш код генерирует значение _id , и вы используете что-то вроде метода guid, это не должно быть проблемой для вас. Однако, если вы оставляете его для генерации Cosmos DB _id (другими словами, вы не указали значение), тогда вам будет гарантирована уникальность в пределах сегмента (раздела), но не обязательно глобально.

2. @DavidMakogon Не могли бы вы уточнить? Как логика на стороне сервера может выдавать «более уникальный» результат, чем сама база данных?

3. Я не говорю, что есть «более уникальный» способ. Я говорю, что если вы создаете guid самостоятельно, вы знаете , что у вас будет уникальный guid независимо от ключа раздела. Вероятно, тот же результат, если вы оставите его для генерации Cosmos DB. Примечание: если вы создаете самостоятельно, у вас будет возможность использовать одно и то же _id значение в разных разделах (сегментах). Принудительное исполнение находится на границе раздела.

Ответ №1:

TL; DR

Это неотъемлемые ограничения в распределенных системах, которые мне нужно принять и, следовательно, перестроить мой процесс проектирования базы данных и программирования доступа к ней? Что в этом случае было бы: ВСЕГДА запрашивать ваши данные из этой коллекции не только по полю _id, но сначала по полю userId? И не рассматривать только мое поле _id как идентификатор, а скорее рассматривать идентификатор как соединение идентификатора пользователя и _id?

Да. В основном.

Более длинная версия

Хотя это поле id not, не являющееся уникальным, на первый взгляд не интуитивно понятно, на самом деле это имеет смысл, учитывая, что CosmosDB стремится к неограниченному масштабированию для точных операций GET / PUT. Это требует, чтобы разделы действовали независимо, и именно здесь происходит большая часть магии. Если id бы или другое уникальное ограничение уникальности применялось бы глобально, то каждое изменение документа должно было бы согласовываться со всеми другими разделами, и это больше не было бы оптимальным или предсказуемым в бесконечном масштабе.

Я также думаю, что это дизайнерское решение по разделению данных соответствует распределенному мышлению CosmosDB без схемы. Если вы используете CosmosDB, примите это и избегайте попыток навязать ему ограничения на междокументальные связи. Вместо этого управляйте ими на уровне проектирования данных / api и клиентской логики. Например, с помощью guid для id.

О ключе раздела..

Может быть, я не могу выбрать правильный ключ раздела? […] ключом раздела должно быть поле, которое наиболее часто используется для фильтрации данных.

Это зависит;). Вы также должны учитывать худшую производительность запросов, а не только «наиболее часто» используемые. Убедитесь, что БОЛЬШИНСТВО запросов могут переходить непосредственно к правильному разделу, что означает, что вы ДОЛЖНЫ знать точный целевой ключ раздела, прежде чем выполнять эти запросы, даже для тех, которые «получить по идентификатору»-запросы. Измерьте стоимость для запросов с перекрестным разделением слева на реалистичном наборе данных.

Трудно сказать, является ли userId это хорошим ключом или нет. Скорее всего, это известно заранее и может быть включено в запросы get-by-id, так что в этом смысле это хорошо. Но вы также должны учитывать:

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

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

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

Комментарии:

1. Спасибо за такой подробный ответ. Есть о чем подумать.