Что мы хотим сделать
В нашем приложении клиенты могут создавать свои собственные отчеты (CSV, Excel, PDF). В приложении они могут объединять до 30 полей для фильтрации и до 20 полей для индивидуальной сортировки (как c & des c). Предварительный просмотр сразу показывается.
История и будущее
Мы разрабатываем и запускаем приложение уже несколько лет. В прошлом мы использовали No Sql RavenDB 3.5, и было очень легко поместить все данные в индекс. Запросы на поля не было проблемой, и результат был довольно быстрым. Например, предварительный просмотр 20 пользовательских отсортированных и отфильтрованных результатов занял менее секунды.
Для последующего продукта мы начали переходить на MongoDB из-за некоторых проблем с RavenDB в прошлом. MongoDB был нашим первым выбором, потому что мы предпочитаем No Sql (легкая настройка, отсутствие ORM, кластер, производительность, стабильность) и большое сообщество и поддерживаемый драйвер. NET. Мы сделали простой PO C во время оценки, и все, кажется, работает нормально. Может быть, это было слишком просто.
Как выглядят наши данные?
Нам нужно запросить более 50 миллионов документов в одной коллекции, и ее структура выглядит следующим образом:
public class Customer {
public Metadata Metadata { get; set; }
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
[BsonRepresentation(BsonType.ObjectId)]
public string PersonId { get; set; }
public int OrderIndex { get; set; }
public DateTime EventTime { get; set; }
public string[] Scopes { get; set; } // hierarchical data e.g.: 12.345.678 or 12.340.000
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public string Sex { get; set; } // male or female or unknown
public string[] Tags { get; set; }
public bool IsLocked { get; set; }
public Address[] Addresses { get; set; }
public int? SomeAmount { get; set; }
public Relation[] Relation { get; set; }
}
Это выдержка из текущего состояния (проекции) клиента. Мы обрабатываем тысячи событий изменений в день и сохраняем состояние в коллекции. В нашей реальной структуре данных у нас более 40 свойств. Структура данных выглядит очень похоже на старое приложение. Фактически, это должно облегчить миграцию.
Сценарии и проблемы использования
Мы предлагаем пользовательский интерфейс, содержащий до 30 полей, которые можно комбинировать, сортировать и оценивать.
Возможные случаи использования:
- Поиск всех лиц старше 30 лет и мужчин, отсортированных по фамилии AS C, FirstName AS C, DateOfBirth AS C
- Запрос: DateOfBirth + Sex; Сортировка: LastName, FirstName, DateOfBirth
- Найти всех людей, живущих в Нью-Йорке, с тегом 'funny', отсортировано по фамилии DES C , Имя AS C, DateOfBirth DES C
- Запрос: Теги + Адрес; Сортировка: DateOfBirth
- Внимание : порядок сортировки изменен. Адрес находится в массиве.
- Найти всех заблокированных лиц, отсортированных по SomeAmount DES C
- Запрос: IsLocked ; Сортировка: SomeAmount
Как видите, существует несколько комбинаций. Поэтому мы не можем использовать один индекс только из-за следующих ограничений :
- строгого порядка полей в составном индексе ( см. )
- Максимум. 32 поля в составном индексе
- смешанные порядки сортировки полей в индексе ( см. )
- в одной коллекции может быть не более 64 индексов (в настоящее время нет проблем)
Сводка
- Всего документов: 50 миллионов
- Средний размер документа: 3 КБ
- Свойства:> 40 (включая вложенные типы и несколько массивы)
- Запрашиваемые поля: ок. 30 (может быть больше)
- Свободно сортируемые поля: до 20 в любой комбинации и направлении (ASC / DES C)
Технические требования
- . NET Core
- MongoDB. NET Драйвер
Вопросы
- Что мы можем сделать для запроса 1-n полей в произвольной сортировке приказ?
- Несколько индексов в каждом порядке полей? Хм, кажется, очень дорого (диск, производительность) и не забудьте: макс. 64 индекса на коллекцию!
- Что делать, если наши клиенты выполняют 40 отчетов одновременно?
- Сортировка выполняется полностью в оперативной памяти, что может привести к значительному снижению производительности. Что такое хорошая стратегия для обработки такого рода нагрузки?
- Что мне делать, если нам нужно запросить более 32 полей?
- Добавить несколько индексов и использовать пересечение индексов ? Это работает для всех видов комбинаций?
- Разделить наш документ на несколько частей и использовать ссылки, хранящиеся в другой коллекции? Чем мы должны работать с $ lookup . Хм, это, вероятно, не очень хорошо работает.
- Является ли MongoDB подходящей базой данных для таких сложных запросов / отчетов?
- Как видите, мы долго думали, но, кажется, ничто не соответствует нашим потребностям.