Учебники

DocumentDB – Разделение

Когда размер вашей базы данных начинает превышать 10 ГБ, вы можете просто расширять ее, создавая новые коллекции, а затем распределяя или разбивая свои данные на все больше и больше коллекций.

Рано или поздно одной коллекции, имеющей емкость 10 ГБ, будет недостаточно для размещения вашей базы данных. Теперь 10 ГБ может показаться не очень большим числом, но помните, что мы храним документы JSON, которые представляют собой просто текст, и вы можете разместить много простых текстовых документов в 10 ГБ, даже если учесть затраты на хранение для индексов.

Хранение не единственная проблема, когда речь заходит о масштабируемости. Максимальная пропускная способность, доступная для коллекции, составляет две с половиной тысячи единиц запроса в секунду, которые вы получаете с коллекцией S3. Следовательно, если вам нужна более высокая пропускная способность, вам также нужно будет масштабировать, разбивая на несколько коллекций. Разделение по горизонтали также называется горизонтальным разделением .

Существует много подходов, которые можно использовать для разделения данных с помощью Azure DocumentDB. Ниже приведены наиболее распространенные стратегии –

  • Побочное Разделение
  • Разделение диапазона
  • Поиск разделов
  • Хеш-разделение

Побочное Разделение

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

  • Побочное разделение начинается с одной коллекции и ключа раздела не существует.

  • Коллекция начинает расти, а затем увеличивается еще немного, а затем еще больше, пока вы не начнете приближаться к пределу в 10 ГБ.

  • Когда вы достигаете 90-процентной емкости, вы перетекаете в новую коллекцию и начинаете использовать ее для новых документов.

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

  • Когда вы сделаете это, вам нужно будет перебалансировать данные, переместив документы в разные коллекции в зависимости от выбранной вами стратегии.

Побочное разделение начинается с одной коллекции и ключа раздела не существует.

Коллекция начинает расти, а затем увеличивается еще немного, а затем еще больше, пока вы не начнете приближаться к пределу в 10 ГБ.

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

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

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

Разделение диапазона

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

  • Даты очень часто используются в этой стратегии, когда вы создаете коллекцию для хранения документов, попадающих в определенный диапазон дат. Когда вы определяете диапазоны, которые достаточно малы, вы уверены, что ни одна коллекция не превысит свой предел в 10 ГБ. Например, может быть сценарий, когда одна коллекция может разумно обрабатывать документы в течение всего месяца.

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

  • В июле вы покупаете другую коллекцию S3 для хранения данных за июль, а также масштабируете июньские данные до менее дорогой коллекции S2. Затем в августе вы получаете еще одну коллекцию S3 и масштабируете июль до S2, а июнь – до S1. Это происходит месяц за месяцем, где вы всегда сохраняете текущие данные доступными для высокой пропускной способности, а старые данные хранятся в доступе для более низких пропускных способностей.

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

Даты очень часто используются в этой стратегии, когда вы создаете коллекцию для хранения документов, попадающих в определенный диапазон дат. Когда вы определяете диапазоны, которые достаточно малы, вы уверены, что ни одна коллекция не превысит свой предел в 10 ГБ. Например, может быть сценарий, когда одна коллекция может разумно обрабатывать документы в течение всего месяца.

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

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

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

Поиск разделов

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

  • Храните все документы США в одной коллекции, все европейские документы в другой коллекции и все документы из любого другого региона в третьей коллекции.

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

Храните все документы США в одной коллекции, все европейские документы в другой коллекции и все документы из любого другого региона в третьей коллекции.

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

Хеш-разделение

В хэш-секционировании разделы назначаются на основе значения хэш-функции, что позволяет равномерно распределять запросы и данные по нескольким разделам.

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

Давайте рассмотрим простой пример разделения диапазонов с использованием RangePartitionResolver, поставляемого .NET SDK.

Шаг 1 – Создайте новый DocumentClient, и мы создадим две коллекции в задаче CreateCollections. Один будет содержать документы для пользователей, которые имеют идентификаторы пользователей, начинающиеся с A до M, а другой – для идентификаторов пользователей от N до Z.

private static async Task CreateCollections(DocumentClient client) {
   await client.CreateDocumentCollectionAsync(“dbs/myfirstdb”, new DocumentCollection {
      Id = CollectionAM }); 
		
   await client.CreateDocumentCollectionAsync(“dbs/myfirstdb”, new DocumentCollection {
      Id = CollectionNZ }); 
}

Шаг 2 – Зарегистрируйте преобразователь диапазона для базы данных.

Шаг 3 – Создайте новый RangePartitionResolver <string>, который является типом данных нашего ключа раздела. Конструктор принимает два параметра: имя свойства ключа раздела и словарь, который является картой сегментов или картой разделов, которая является просто списком диапазонов и соответствующих коллекций, которые мы предварительно определяем для распознавателя.

private static void RegisterRangeResolver(DocumentClient client) {

   //Note: \uffff is the largest UTF8 value, so M\ufff includes all strings that start with M.
		
   var resolver = new RangePartitionResolver<string>(
      "userId", new Dictionary<Range<string>, string>() {
      { new Range<string>("A", "M\uffff"), "dbs/myfirstdb/colls/CollectionAM" },
      { new Range<string>("N", "Z\uffff"), "dbs/myfirstdb/colls/CollectionNZ" },
   });
	
   client.PartitionResolvers["dbs/myfirstdb"] = resolver;
 }

Здесь необходимо закодировать максимально возможное значение UTF-8. В противном случае первый диапазон не будет совпадать ни с одним M, кроме одного M, а также для Z во втором диапазоне. Таким образом, вы можете просто подумать об этом закодированном значении здесь как о подстановочном знаке для соответствия ключу раздела.

Шаг 4 – После создания распознавателя зарегистрируйте его для базы данных с текущим DocumentClient. Для этого просто присвойте его свойству словаря PartitionResolver.

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

Теперь давайте создадим несколько документов. Сначала мы создадим один для userId Кирка, а затем один для Спока.

private static async Task CreateDocumentsAcrossPartitions(DocumentClient client) { 
   Console.WriteLine(); 
   Console.WriteLine("**** Create Documents Across Partitions ****");
	
   var kirkDocument = await client.CreateDocumentAsync("dbs/myfirstdb", new { userId =
      "Kirk", title = "Captain" }); 
   Console.WriteLine("Document 1: {0}", kirkDocument.Resource.SelfLink);
	
   var spockDocument = await client.CreateDocumentAsync("dbs/myfirstdb", new { userId =
      "Spock", title = "Science Officer" });		
   Console.WriteLine("Document 2: {0}", spockDocument.Resource.SelfLink); 
}

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

Оба документа были сохранены в базе данных myfirstdb, но мы знаем, что Кирк хранится в коллекции от A до M, а Spock хранится в коллекции от N до Z, если наш RangePartitionResolver работает правильно.

Давайте вызовем их из задачи CreateDocumentClient, как показано в следующем коде.

private static async Task CreateDocumentClient() {
   // Create a new instance of the DocumentClient 
   using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
      await CreateCollections(client);  
      RegisterRangeResolver(client);  
      await CreateDocumentsAcrossPartitions(client); 
   } 
}

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

**** Create Documents Across Partitions **** 
Document 1: dbs/Ic8LAA==/colls/Ic8LAO2DxAA=/docs/Ic8LAO2DxAABAAAAAAAAAA==/ 
Document 2: dbs/Ic8LAA==/colls/Ic8LAP12QAE=/docs/Ic8LAP12QAEBAAAAAAAAAA==/

Как видно, собственные ссылки двух документов имеют разные идентификаторы ресурсов, поскольку они существуют в двух отдельных коллекциях.