Предположим, что приложение для чата насчитывает 10 миллионов пользователей Firebase и сотни миллионов сообщений.
У меня есть коллекция Firestore, содержащая сообщения, представленные в виде документов во временном ряду, и каждое из этих сообщений может быть получено и просмотрено до 100 из этих пользователей. Обратите внимание, что эти пользователи не организованы в стабильные группы, поскольку каждое сообщение может иметь совершенно другой набор пользователей, которые его получают.
Я должен быть в состоянии найти, очень эффективно (с точки зрения времени и стоимости),
все сообщения через определенное время, направленные какому-то конкретному пользователю.
Моей первой неудачной попыткой было бы перечислить пользователей-получателей в поле массива recipients
, например:
sender: user3567381
dateTime : 2019-01-24T20:37:28Z
recipients : [user1033029, user9273842, user8293413, user6273581]
Однако это не позволит мне эффективно выполнять свои запросы.
В качестве второй неудачной попытки , поскольку Firestore не имеет схемы, я подумал о превращении каждого пользователя в поле , например:
sender: user3567381
dateTime : 2019-01-24T20:37:28Z
user1033029 : true
user9273842 : true
user8293413 : true
user6273581 : true
Тогда, например, если я хочу узнать все сообщения для пользователя 8293413 после 15:00 сегодня, я мог бы сделать это так:
messages.where("user8293413", "==", true).where("dateTime", ">=", "2019-01-24T15:00:00Z")
Это запрос составного индекса, и для него потребуется один индекс на пользователя. К сожалению, существует ограничение 200 составных индексов на базу данных.
Чтобы решить эту проблему, моя текущая попытка состоит в том, чтобы превратить date в значения пользовательских полей, например:
sender: user3567381
dateTime : 2019-01-24T20:37:28Z
user1033029 : 2019-01-24T20:37:28Z
user9273842 : 2019-01-24T20:37:28Z
user8293413 : 2019-01-24T20:37:28Z
user6273581 : 2019-01-24T20:37:28Z
Теперь, если я хочу узнать все сообщения для пользователя 8293413 после 15:00 сегодня, я мог бы сделать это так:
messages.where("user8293413", ">=", "2019-01-24T15:00:00Z")
Обратите внимание, что теперь это индекс с одним полем .
Из документации я знаю, что Firestore создаст однополевые индексы для всех полей, поэтому это означает, что он будет создавать индексы для пользователя 8293413 в частности.
Это значит, что поиск будет быстрым, верно? И что количество чтений будет сведено к минимуму (одно чтение на сообщение).
Однако, поскольку у меня 10 миллионов пользователей, Firestore должен будет создать 10 миллионов индексов с одним полем (при условии, что все пользователи получают сообщения) для всей базы данных.
Из документации Firestore имеет следующие ограничения:
- Максимальное количество составных индексов для базы данных: 200
- Максимальное количество исключений индекса одного поля для базы данных: 200
- Максимальное количество записей индекса для каждого документа: 40 000 (Количество записей индекса представляет собой сумму следующего для документа: Количество записей индекса в одном поле + Количество записей составного индекса )
- Максимальный размер записи индекса: 7,5 КиБ
- Максимальная сумма размеров элементов индекса документа: 8 МБ (Общий размер - это сумма следующих значений для документа: сумма размера записей индекса одного поля документа + Сумма размера записей составного индекса документа)
- Максимальный размер значения индексированного поля: 1500 байтов (Значения поля более 1500 байтов усекаются. Запросы, содержащие усеченные значения поля, могут возвращать противоречивые результаты.)
Читая выше, они привлекают мое внимание:
- Максимальное количество записей индекса для каждого документа: 40000
- Максимальная сумма размеров индексных записей документа: 8 МиБ
Однако они заявляют, что ограничение составляет для каждого документа , а не для каждой базы данных. И у меня есть только миллионы индексов для базы данных, а не для каждого документа.
Это проблема? Повлияет ли так много индексов на производительность? Как насчет стоимости хранения всех этих индексов? Готов ли Firebase к большому общему количеству индексов на базу данных?