Перенос несекционированных контейнеров в секционированные контейнеры

ОБЛАСТЬ ПРИМЕНЕНИЯ: NoSQL

Azure Cosmos DB поддерживает возможность создания контейнеров без ключа секции. В настоящее время можно создавать несекционированные контейнеры с помощью Azure CLI и пакетов SDK для Azure Cosmos DB (.NET, Java, NodeJs), версия которых меньше или равна 2.x. Вы не можете создавать несекционированные контейнеры с помощью портал Azure. Однако такие несекционированные контейнеры не являются эластичными и имеют фиксированную емкость хранилища 20 ГБ и ограничение пропускной способности в 10 000 единиц запросов в секунду.

Несекционированные контейнеры являются устаревшими, поэтому необходимо перенести существующие несекционированные контейнеры в секционированные контейнеры для масштабирования хранилища и пропускной способности. Azure Cosmos DB предоставляет системный механизм для переноса несекционированных контейнеров в секционированные контейнеры. В этом документе объясняется, как все существующие несекционированные контейнеры автоматически переносятся в секционированные контейнеры. Вы можете воспользоваться функцией автоматического переноса, только если вы используете версию sdk версии 3 на всех языках.

Примечание

В настоящее время вы не можете перенести MongoDB и API Azure Cosmos DB для учетных записей Gremlin, выполнив действия, описанные в этом документе.

Перенос контейнера с помощью системного ключа секции

В целях миграции Azure Cosmos DB предоставляет системный ключ секции /_partitionkey для всех контейнеров, у которых нет ключа секции. Вы не можете изменить определение ключа секции после переноса контейнеров. Например, определение контейнера, перенесенного в секционированный контейнер, будет выглядеть следующим образом:

{
    "Id": "CollId"
  "partitionKey": {
    "paths": [
      "/_partitionKey"
    ],
    "kind": "Hash"
  },
}

После переноса контейнера можно создавать документы, заполняя свойство _partitionKey вместе с другими свойствами документа. Свойство _partitionKey представляет ключ секции документов.

Выбор правильного ключа секции важен для оптимального использования подготовленной пропускной способности. Дополнительные сведения см. в статье о выборе ключа секции.

Примечание

Функция системного ключа секции доступна, только если используются пакеты SDK последней версии или версии 3 на всех языках.

Ниже показан пример кода для создания документа с системным ключом секции и для его чтения:

JSON-представление документа

DeviceInformationItem = new DeviceInformationItem
{
   "id": "elevator/PugetSound/Building44/Floor1/1",
   "deviceId": "3cf4c52d-cc67-4bb8-b02f-f6185007a808",
   "_partitionKey": "3cf4c52d-cc67-4bb8-b02f-f6185007a808"
}

public class DeviceInformationItem
{
    [JsonProperty(PropertyName = "id")]
    public string Id { get; set; }

    [JsonProperty(PropertyName = "deviceId")]
    public string DeviceId { get; set; }

    [JsonProperty(PropertyName = "_partitionKey", NullValueHandling = NullValueHandling.Ignore)]
    public string PartitionKey { get {return this.DeviceId; set; }
}

CosmosContainer migratedContainer = database.Containers["testContainer"];

DeviceInformationItem deviceItem = new DeviceInformationItem() {
  Id = "1234",
  DeviceId = "3cf4c52d-cc67-4bb8-b02f-f6185007a808"
}

ItemResponse<DeviceInformationItem > response =
  await migratedContainer.CreateItemAsync<DeviceInformationItem>(
    deviceItem.PartitionKey,
    deviceItem
  );

// Read back the document providing the same partition key
ItemResponse<DeviceInformationItem> readResponse =
  await migratedContainer.ReadItemAsync<DeviceInformationItem>(
    partitionKey: deviceItem.PartitionKey,
    id: device.Id
  );

Полный пример см. в репозитории примеров .NET на сайте GitHub.

Перенос документов

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

Доступ к документам, у которых нет ключа секции

Приложения могут обращаться к существующим документам, у которых нет ключа секции, с помощью специального системного свойства под названием "PartitionKey.None" (это значение для неперенесенных документов). Это свойство можно использовать во всех операциях CRUD и запросах. Ниже показан пример чтения одного документа из раздела NonePartitionKey.

CosmosItemResponse<DeviceInformationItem> readResponse =
await migratedContainer.Items.ReadItemAsync<DeviceInformationItem>(
  partitionKey: PartitionKey.None,
  id: device.Id
);

Совместимость с SDK

Более старые версии SDK для Azure Cosmos DB, такие как 2.x.x и 1.x.x, не поддерживают свойство системного ключа секции. Таким образом, при чтении определения контейнера из старого пакета SDK оно не содержит определения ключа секции, и такие контейнеры работают точно так же, как и раньше. Приложения, созданные с помощью более старой версии пакетов SDK, продолжают работать с несекционированных без изменений.

Если перенесенный контейнер используется в последней версии пакета SDK или версии 3 и вы начинаете заполнять ключ секции, определенный системой, в новых документах, вы больше не сможете получить доступ к таким документам (чтение, обновление, удаление, запрос) из старых пакетов SDK.

Известные проблемы

Запрос количества элементов, которые были вставлены без ключа секции с помощью пакета SDK версии 3, может привести к повышению потребляемой пропускной способности.

При запросе из пакета SDK версии 3 элементов, вставленных с помощью пакета SDK версии 2, или элементов, вставленных с помощью пакета SDK версии 3 с параметром PartitionKey.None, запрос количества может потреблять больше ЕЗ/с, если в FeedOptions указан параметр PartitionKey.None. Рекомендуем не указывать параметр PartitionKey.None, если с ключом секции не вставляются больше никакие другие элементы.

Если новые элементы вставляются с разными значениями для ключа секции, запросы к таким счетчикам элементов путем передачи соответствующего ключа в FeedOptions не будут иметь никаких проблем. Если после вставки новых документов с ключом секции потребуется запросить только количество документов без значения ключа секции, этот запрос также может потребить больше ЕЗ/с (так же, как в обычных коллекциях с секционированием).

Дальнейшие действия