Индексы – важный фактор производительности базы данных. Подобно указателю книги, который сопоставляет темы в книге с номерами страниц, индекс базы данных сопоставляет элементы в базе данных с их местоположением в базе данных. Когда вы запрашиваете базу данных, она может использовать индекс, чтобы быстро определить местоположение запрашиваемых вами элементов.
На этой странице описаны два типа индексов, которые использует Cloud Firestore: автоматические и созданные вручную.
Определение и структура индекса
Индекс определяется по списку полей заданного документа с соответствующим режимом индекса для каждого поля.
Индекс содержит запись для каждого поля, указанного в определении индекса. В индекс включаются все документы, которые могут быть показаны в результатах поиска по запросам, связанным с этим индексом. Документ включается в индекс, только если для каждого поля, используемого в индексе, задано индексированное значение. Если в определении индекса указано поле, для которого в документе не задано значение, этот документ не будет включен в индекс. В этом случае документ никогда не будет возвращен в качестве результата для любого запроса на основе индекса.
Индекс сортируется по значениям полей в порядке, указанном в определении индекса.
Индекс для каждого запроса
Если для запроса нет индекса, большинство баз данных просматривают свое содержимое элемент за элементом. Это медленный процесс, который замедляется ещё больше по мере роста базы данных. Cloud Firestore обеспечивает высокую производительность запросов, используя индексы для всех запросов. В результате эффективность запроса зависит от размера набора результатов, а не от количества элементов в базе данных.
Меньше управления индексами, больше разработки приложений
Cloud Firestore включает функции, которые сокращают время, необходимое для управления индексами. Индексы, необходимые для самых простых запросов, создаются автоматически. Когда вы используете и тестируете приложение, Cloud Firestore помогает вам определить и создать дополнительные индексы, которые требуются приложению.
Типы индекса
Cloud Firestore использует два типа индексов: автоматические и созданные вручную. Разница между ручными и автоматическими индексами заключается в способе управления ими.
Автоматические индексы
По умолчанию Cloud Firestore автоматически создает индексы для каждого поля, присутствующего в документах коллекции. Эти индексы по одному полю позволяют выполнять множество базовых запросов. Вы можете управлять автоматическими индексами, настраивая параметры автоматического индексирования и исключения индексов в базе данных.
Автоматическое индексирование по умолчанию
В Cloud Firestore для автоматических индексов по умолчанию используются следующие настройки:
Для каждого поля, не являющегося массивом или картой, Cloud Firestore определяет два индекса области действия коллекции: один в режиме по возрастанию и один в режиме по убыванию.
Для каждого сопоставленного поля Cloud Firestore создает:
- Один индекс по возрастанию в области коллекции для каждого подполя, не являющегося массивом или картой.
- Один индекс по убыванию в области коллекции для каждого подполя, не являющегося массивом или картой.
- Один индекс по возрастанию в области коллекции для всего значения карты.
- Один индекс по убыванию в области коллекции для всего значения карты.
- Один индекс array-contains на уровне коллекции для каждого подполя массива.
- Cloud Firestore рекурсивно индексирует каждое подполе карты.
Для каждого поля массива в документе Cloud Firestore создает следующее:
- Один индекс по возрастанию на уровне коллекции для всего значения массива.
- Один индекс по убыванию на уровне коллекции для всего значения массива.
- Один индекс array-contains на уровне коллекции.
Автоматические индексы с областью действия группы коллекций по умолчанию не поддерживаются.
Исключения для автоматического индексирования
Вы можете исключить поле из автоматической индексации, создав исключение. Исключение индексирования переопределяет настройки автоматического индексирования на уровне базы данных. Исключение может включить индекс, который в противном случае был бы отключен настройками автоматического индексирования, или отключить индекс, который в противном случае был бы включен автоматическим индексированием. Примеры ситуаций, в которых могут быть полезны исключения, приведены в рекомендациях по индексированию.
Используйте значение пути поля *, чтобы добавить исключения индексов на уровне коллекции для всех полей в группе коллекций. Например, для группы коллекций comments задайте путь к полю *, чтобы сопоставить все поля в группе коллекций comments и отключить индексирование всех полей в группе коллекций. Затем вы можете добавить исключения, чтобы индексировать только поля, необходимые для ваших запросов. Уменьшение количества индексированных полей снижает затраты на хранение и может повысить производительность записи.
Если вы создадите исключение для поля карты, его настройки будут унаследованы подполями. Однако вы можете определить исключения индекса для определенных подполей. Если вы удалите исключение для подполя, оно унаследует настройки исключения родительского поля (если они есть) или настройки на уровне базы данных (если исключений для родительского поля нет).
Чтобы создать исключения для автоматического индексирования и управлять ими, ознакомьтесь со статьей Управление индексами.
Индексы, созданные вручную
В ручном индексе хранится отсортированное сопоставление всех документов в коллекции на основе упорядоченного списка полей для индексирования.
Cloud Firestore использует индексы, созданные вручную, для поддержки запросов, которые не поддерживаются автоматическими индексами.
По умолчанию Cloud Firestore автоматически создает индексы для каждого поля в коллекции. Cloud Firestore не создает индексы для комбинаций полей автоматически, поскольку таких комбинаций может быть очень много. Вместо этого Cloud Firestore помогает вам определять и создавать необходимые индексы по мере создания приложения.
Если вы попытаетесь выполнить запрос, который не поддерживается существующим индексом, Cloud Firestore вернет сообщение об ошибке со ссылкой, по которой можно создать отсутствующий индекс.
Вы также можете определять индексы и управлять ими вручную в консоли или с помощью интерфейса командной строки Firebase. Подробнее о том, как создавать индексы вручную и управлять ими…
Режимы индексирования и области действия запросов
Автоматические и созданные вручную индексы настраиваются по-разному, но для обоих типов нужно задать режимы индексирования и области запросов.
Режимы индексирования
При определении индекса вы выбираете режим индексирования для каждого индексированного поля. Каждый режим индексирования поля поддерживает определенные предложения запроса для этого поля. Доступны следующие режимы индексирования:
| Режим индекса | Описание |
|---|---|
| По возрастанию | Поддерживает предложения запроса <, <=, ==, >=, >, !=, in и not-in в поле и сортировку результатов по возрастанию на основе значения этого поля. |
| По убыванию | Поддерживает предложения запроса <, <=, ==, >=, >, !=, in и not-in в поле и сортировку результатов в порядке убывания на основе значения этого поля. |
| Array‑contains | Поддерживает условия запроса array-contains и array-contains-any для поля. |
| Вектор | Поддерживает операторы запросов FindNearest для этого поля. |
Области действия запросов
Каждый индекс относится к коллекции или группе коллекций. Это называется областью запроса индекса:
- Область действия коллекции По умолчанию
- Cloud Firestore создает индексы с областью действия на уровне коллекции. Эти индексы поддерживают запросы, которые возвращают результаты из одной коллекции.
- Область действия группы коллекций
- Группа коллекций включает все коллекции с одинаковым идентификатором. Чтобы выполнить запрос к группе коллекций, который возвращает отфильтрованные или упорядоченные результаты, необходимо создать соответствующий индекс с областью действия группы коллекций.
Сортировка по умолчанию и поле __name__
Помимо сортировки документов по режимам индекса, указанным для каждого поля (по возрастанию или по убыванию), индексы применяют окончательную сортировку по полю __name__ каждого документа. Значение поля __name__ – полный путь к документу. Это означает, что документы в наборе результатов с одинаковыми значениями полей сортируются по пути к документу.
По умолчанию поле __name__ сортируется в том же направлении, что и последнее отсортированное поле в определении индекса. Пример:
| Коллекция | Проиндексированные поля | Область действия запроса |
|---|---|---|
| города | , __name__ |
Коллекция |
| города | , __name__ |
Коллекция |
| города | страна, население, __name__ |
Коллекция |
Чтобы сортировать результаты по направлению __name__, которое не используется по умолчанию, нужно создать индекс.
Свойства индекса
Индекс, который позволяет выполнить запрос наиболее эффективно, определяется следующими свойствами:
- Поля, используемые в фильтрах равенства
- Поля, используемые в порядке сортировки
- Поля, используемые в фильтрах диапазонов и неравенств (которые ещё не включены в порядок сортировки).
- Поля, используемые в агрегировании (которые ещё не включены в порядок сортировки и фильтры диапазонов и неравенств).
Cloud Firestore вычисляет результаты запросов следующим образом:
- Определяет индекс, соответствующий коллекции запроса, свойствам фильтра, операторам фильтра и порядку сортировки.
- Определяет позицию индекса, с которой начинается сканирование. Начальная позиция определяется фильтрами равенства, а конечная – фильтрами диапазона и неравенства для первого поля
orderBy. - Начинает сканирование индекса и возвращает каждый документ, соответствующий всем фильтрам, пока не произойдет одно из следующих событий:
- Обнаруживает документ, который не соответствует условиям фильтра, и подтверждает, что ни один последующий документ не будет полностью соответствовать условиям фильтра.
- Достигнут конец индекса.
- Собирает максимальное количество результатов, запрошенных запросом.
Пример индексирования
Автоматически создавая для вас индексы по одному полю, Cloud Firestore позволяет вашему приложению быстро поддерживать самые базовые запросы к базе данных.
Индексы по одному полю позволяют выполнять простые запросы на основе значений полей и операторов сравнения <, <=, ==, >=, > и in. Для полей массивов они позволяют выполнять запросы array-contains и array-contains-any.
Чтобы проиллюстрировать это, рассмотрим следующие примеры с точки зрения создания индекса. Следующий фрагмент кода создает несколько документов city в коллекции cities и задает поля name, state, country, capital, population и regions для каждого документа:
Веб-приложение
var citiesRef = db.collection("cities"); citiesRef.doc("SF").set({ name: "San Francisco", state: "CA", country: "USA", capital: false, population: 860000, regions: ["west_coast", "norcal"] }); citiesRef.doc("LA").set({ name: "Los Angeles", state: "CA", country: "USA", capital: false, population: 3900000, regions: ["west_coast", "socal"] }); citiesRef.doc("DC").set({ name: "Washington, D.C.", state: null, country: "USA", capital: true, population: 680000, regions: ["east_coast"] }); citiesRef.doc("TOK").set({ name: "Tokyo", state: null, country: "Japan", capital: true, population: 9000000, regions: ["kanto", "honshu"] }); citiesRef.doc("BJ").set({ name: "Beijing", state: null, country: "China", capital: true, population: 21500000, regions: ["jingjinji", "hebei"] });
При настройках автоматического индексирования по умолчанию Cloud Firestore обновляет один индекс по возрастанию для каждого поля, один индекс по убыванию для каждого поля и один индекс array-contains для поля массива. Каждая строка в следующей таблице представляет собой запись в индексе по одному полю:
| Коллекция | Поле проиндексировано | Область действия запроса |
|---|---|---|
| города | Название ресурса "" | Коллекция |
| города | штат | Коллекция |
| города | страна | Коллекция |
| города | Столица: | Коллекция |
| города | Коллекция | |
| города | регионов | Коллекция |
| города | Название ресурса "" | Коллекция |
| города | штат | Коллекция |
| города | страна | Коллекция |
| города | Столица: | Коллекция |
| города | Коллекция | |
| города | регионов | Коллекция |
| города | array-contains регионов |
Коллекция |
Запросы, поддерживаемые индексами по одному полю
Используя эти автоматически созданные индексы для одного поля, вы можете выполнять простые запросы, например:
Веб-приложение
const stateQuery = citiesRef.where("state", "==", "CA"); const populationQuery = citiesRef.where("population", "<", 100000); const nameQuery = citiesRef.where("name", ">=", "San Francisco");
Вы также можете создавать запросы с операторами in и составными операторами равенства (==):
Веб-приложение
citiesRef.where('country', 'in', ["USA", "Japan", "China"])
// Compound equality queries
citiesRef.where("state", "==", "CO").where("name", "==", "Denver")
citiesRef.where("country", "==", "USA")
.where("capital", "==", false)
.where("state", "==", "CA")
.where("population", "==", 860000)Если вам нужно выполнить составной запрос, в котором используется сравнение диапазонов (<, <=, > или >=), или если вам нужно выполнить сортировку по другому полю, вы должны создать индекс вручную для этого запроса.
Индекс array-contains позволяет запрашивать поле массива regions:
Веб-приложение
citiesRef.where("regions", "array-contains", "west_coast") // array-contains-any and array-contains use the same indexes citiesRef.where("regions", "array-contains-any", ["west_coast", "east_coast"])
Запросы, поддерживаемые индексами, созданными вручную
Создайте индексы вручную, чтобы обеспечить поддержку составных запросов, которые не поддерживаются автоматическими индексами по одному полю. Например, вам потребуется индекс, созданный вручную, для следующих запросов:
Веб-приложение
citiesRef.where("country", "==", "USA").orderBy("population", "asc")
citiesRef.where("country", "==", "USA").where("population", "<", 3800000)
citiesRef.where("country", "==", "USA").where("population", ">", 690000)
// in and == clauses use the same index
citiesRef.where("country", "in", ["USA", "Japan", "China"])
.where("population", ">", 690000)Для этих запросов требуется следующий индекс. Поскольку в запросе используется равенство (== или in) для поля country, вы можете использовать для этого поля режим индекса по возрастанию или по убыванию. По умолчанию предложения неравенства применяют порядок сортировки по возрастанию на основе поля в предложении неравенства.
| Коллекция | Проиндексированные поля | Область действия запроса |
|---|---|---|
| города | (или ) страна, население | Коллекция |
Чтобы выполнить те же запросы, но с порядком сортировки по убыванию, вам понадобится дополнительный индекс в направлении по убыванию для population:
Веб-приложение
citiesRef.where("country", "==", "USA").orderBy("population", "desc")
citiesRef.where("country", "==", "USA")
.where("population", "<", 3800000)
.orderBy("population", "desc")
citiesRef.where("country", "==", "USA")
.where("population", ">", 690000)
.orderBy("population", "desc")
citiesRef.where("country", "in", ["USA", "Japan", "China"])
.where("population", ">", 690000)
.orderBy("population", "desc")| Коллекция | Проиндексированные поля | Область действия запроса |
|---|---|---|
| города | страна, | Коллекция |
| города | страна, население | Коллекция |
Чтобы избежать снижения производительности, вызванного объединением индексов, рекомендуем создать индекс, который будет объединять запрос array-contains или array-contains-any с дополнительными условиями.
Веб-приложение
citiesRef.where("regions", "array-contains", "east_coast") .where("capital", "==", true) // array-contains-any and array-contains use the same index citiesRef.where("regions", "array-contains-any", ["west_coast", "east_coast"]) .where("capital", "==", true)
| Коллекция | Проиндексированные поля | Область действия запроса |
|---|---|---|
| города | Теги array-contains, (или ) заглавными буквами | Коллекция |
Запросы, поддерживаемые индексами группы коллекций
Чтобы продемонстрировать индекс с областью действия группы коллекций, добавьте подколлекцию landmarks в некоторые документы city:
Веб-приложение
var citiesRef = db.collection("cities"); citiesRef.doc("SF").collection("landmarks").doc().set({ name: "Golden Gate Bridge", category : "bridge" }); citiesRef.doc("SF").collection("landmarks").doc().set({ name: "Golden Gate Park", category : "park" }); citiesRef.doc("DC").collection("landmarks").doc().set({ name: "National Gallery of Art", category : "museum" }); citiesRef.doc("DC").collection("landmarks").doc().set({ name: "National Mall", category : "park" });
Используя следующий индекс по одному полю с областью действия коллекции, вы можете запросить коллекцию landmarks одного города на основе поля category:
| Коллекция | Проиндексированные поля | Область действия запроса |
|---|---|---|
| достопримечательности | Категория (или ) | Коллекция |
Веб-приложение
citiesRef.doc("SF").collection("landmarks").where("category", "==", "park")
citiesRef.doc("SF").collection("landmarks").where("category", "in", ["park", "museum"])Если вы хотите запросить достопримечательности во всех городах, например,
вы запускаете этот запрос в группе коллекций, которая состоит из всех коллекций landmarks. Вам также необходимо включить landmarks индекс одного поля с областью действия группы коллекций:
| Коллекция | Проиндексированные поля | Область действия запроса |
|---|---|---|
| достопримечательности | Категория (или ) | Группа коллекций |
Если этот индекс включен, вы можете запрашивать группу коллекций landmarks:
Веб-приложение
var landmarksGroupRef = db.collectionGroup("landmarks"); landmarksGroupRef.where("category", "==", "park") landmarksGroupRef.where("category", "in", ["park", "museum"])
Чтобы выполнить запрос к группе коллекций, который возвращает отфильтрованные или упорядоченные результаты, необходимо включить соответствующий индекс с областью действия группы коллекций. Однако для запросов к группе коллекций, которые не фильтруют и не упорядочивают результаты, не требуются дополнительные определения индексов.
Например, вы можете выполнить следующий запрос группы коллекций, не включая дополнительный индекс:
Веб-приложение
db.collectionGroup("landmarks").get()Записи в индексе
Количество записей в индексе для документа определяется настроенными индексами проекта и структурой документа. Записи в индексе учитываются в ограничении на количество записей в индексе.
В примере ниже показаны записи в индексе для документа.
Документ
/cities/SF
city_name : "San Francisco"
temperatures : {summer: 67, winter: 55}
neighborhoods : ["Mission", "Downtown", "Marina"]
Автоматические индексы
- city_name ASC
- city_name DESC
- Районы (по возрастанию)
- neighborhoods DESC
- temperatures ASC
- temperatures DESC
- temperatures.summer ASC
- temperatures.summer DESC
- temperatures.winter ASC
- temperatures.winter DESC
- neighborhoods Array Contains
Индексы, созданные вручную
- city_name ASC, neighborhoods ARRAY
- city_name DESC, neighborhoods ARRAY
Записи в индексе
В результате такой настройки индексирования для документа будут созданы следующие записи в индексе:
| Номер | Проиндексированные данные |
|---|---|
| Автоматические записи в индексе | |
| city_name ASC | city_name: "Сан-Франциско" |
| city_name DESC | city_name: "Сан-Франциско" |
| Районы (по возрастанию) | neighborhoods: ["Mission", "Downtown", "Marina"] |
| neighborhoods DESC | neighborhoods: ["Mission", "Downtown", "Marina"] |
| temperatures ASC | temperatures: {summer: 67, winter: 55} |
| temperatures DESC | temperatures: {summer: 67, winter: 55} |
| temperatures.summer ASC | temperatures.summer: 67 |
| temperatures.summer DESC | temperatures.summer: 67 |
| temperatures.winter ASC | temperatures.winter: 55 |
| temperatures.winter DESC | temperatures.winter: 55 |
| neighborhoods Array Contains | neighborhoods: "Mission" |
| neighborhoods Array Contains | neighborhoods: "Downtown" |
| neighborhoods Array Contains | neighborhoods: "Marina" |
| Записи в индексе, созданные вручную | |
| city_name ASC, neighborhoods ARRAY | city_name: "Сан-Франциско", neighborhoods: "Мишн" |
| city_name ASC, neighborhoods ARRAY | city_name: "Сан-Франциско", neighborhoods: "Центр" |
| city_name ASC, neighborhoods ARRAY | city_name: "Сан-Франциско", neighborhoods: "Марина" |
| city_name DESC, neighborhoods ARRAY | city_name: "Сан-Франциско", neighborhoods: "Мишн" |
| city_name DESC, neighborhoods ARRAY | city_name: "Сан-Франциско", neighborhoods: "Центр" |
| city_name DESC, neighborhoods ARRAY | city_name: "Сан-Франциско", neighborhoods: "Марина" |
Индексы и цены
Индексы влияют на стоимость хранения данных приложения. Подробнее о том, как рассчитать размер хранилища для записей в индексе.
Используйте объединение индексов
Хотя Cloud Firestore использует индекс для каждого запроса, это не означает, что для каждого запроса требуется отдельный индекс. Для запросов с несколькими условиями равенства (==) и, возможно, условием orderBy Cloud Firestore может повторно использовать существующие индексы. Cloud Firestore может объединять индексы для простых фильтров равенства, чтобы создавать индексы, необходимые для более крупных запросов равенства.
Вы можете снизить расходы на индексирование, определив ситуации, в которых можно использовать объединение индексов. Например, в коллекции restaurants для приложения с рейтингом ресторанов:
ресторанов
burgerthyme
name : "Burger Thyme"
category : "burgers"
city : "San Francisco"
editors_pick : true
star_rating : 4
В этом приложении используются запросы, подобные приведенным ниже. Приложение использует комбинации условий равенства для category, city и editors_pick, всегда сортируя по возрастанию star_rating:
Веб-приложение
db.collection("restaurants").where("category", "==", "burgers")
.orderBy("star_rating")
db.collection("restaurants").where("city", "==", "San Francisco")
.orderBy("star_rating")
db.collection("restaurants").where("category", "==", "burgers")
.where("city", "==", "San Francisco")
.orderBy("star_rating")
db.collection("restaurants").where("category", "==", "burgers")
.where("city", "==", "San Francisco")
.where("editors_pick", "==", true )
.orderBy("star_rating")Вы можете создать индекс для каждого запроса:
| Коллекция | Проиндексированные поля | Область действия запроса |
|---|---|---|
| рестораны | Категория: , оценка: | Коллекция |
| рестораны | city, star_rating | Коллекция |
| рестораны | category, city, star_rating | Коллекция |
| рестораны | категория, город, выбор редакции, оценка | Коллекция |
Лучше сократить количество индексов, воспользовавшись возможностью Cloud Firestore объединять индексы для условий равенства:
| Коллекция | Проиндексированные поля | Область действия запроса |
|---|---|---|
| рестораны | Категория: , оценка: | Коллекция |
| рестораны | city, star_rating | Коллекция |
| рестораны | editors_pick, star_rating | Коллекция |
Этот набор индексов не только меньше, но и поддерживает дополнительный запрос:
Веб-приложение
db.collection("restaurants").where("editors_pick", "==", true)
.orderBy("star_rating")Ограничения на индексирование
Для индексов действуют следующие ограничения: Подробнее о квотах и ограничениях…
| Ограничение | Сведения |
|---|---|
| Максимальное количество составных индексов для базы данных |
|
| Максимальное количество конфигураций с одним полем для базы данных |
В одной конфигурации на уровне поля может быть несколько конфигураций для одного поля. Например, исключение из индексирования одного поля и правило TTL для того же поля считаются одной конфигурацией поля. |
|
Максимальное количество записей в индексе для каждого документа |
40 000 Количество записей в индексе для документа рассчитывается как сумма следующих значений:
Чтобы узнать, как Cloud Firestore преобразует документ и набор индексов в записи в индексе, ознакомьтесь с этим примером подсчета записей в индексе. |
| Максимальное количество полей в составном индексе | 100 |
| Максимальный размер записи в индексе |
7,5 КиБ Чтобы узнать, как Cloud Firestore рассчитывает размер записи в индексе, ознакомьтесь с разделом Размер записи в индексе. |
| Максимальная сумма размеров записей в индексе документа |
8 МиБ Общий размер документа складывается из следующих значений: |
| Максимальный размер значения индексированного поля |
1500 байт Значения полей, превышающие 1500 байт, усекаются. Запросы, включающие усеченные значения полей, могут возвращать противоречивые результаты. |
Рекомендации по индексированию
Для большинства приложений можно использовать автоматическое индексирование и ссылки в сообщениях об ошибках, чтобы управлять индексами. Однако в некоторых случаях может потребоваться добавить исключения для автоматического индексирования:
| Падеж | Описание |
|---|---|
| Большие строковые поля | Если у вас есть строковое поле, которое часто содержит длинные строковые значения, которые вы не используете для запросов, вы можете сократить расходы на хранение, исключив поле из индексации. |
| Высокая скорость записи в коллекцию, содержащую документы с последовательными значениями. | Если вы индексируете поле, которое последовательно увеличивается или уменьшается между документами в коллекции, например временную метку, то максимальная скорость записи в коллекцию составляет 500 записей в секунду. Если вы не выполняете запросы на основе поля с последовательными значениями, вы можете исключить это поле из индексирования, чтобы обойти это ограничение. Например, в случае использования IoT с высокой скоростью записи коллекция, содержащая документы с полем временной метки, может приблизиться к пределу в 500 записей в секунду. |
| Поля TTL |
Если вы используете правила TTL (время жизни), обратите внимание, что поле TTL должно быть временной меткой. Индексирование полей TTL включено по умолчанию и может влиять на производительность при более высоких показателях трафика. Рекомендуем добавить исключения автоматического индексирования для полей TTL. |
| Большие массивы или поля карт | Большие массивы или поля карт могут приближаться к пределу в 40 000 записей в индексе на документ. Если вы не выполняете запросы на основе большого массива или поля карты, вам следует исключить его из индексации. |
Если вы используете запросы с операторами диапазона и неравенства в нескольких полях, ознакомьтесь с рекомендациями по индексированию, которые следует учитывать для оптимизации производительности и стоимости запросов Cloud Firestore.
Дополнительную информацию о том, как устранять проблемы с индексированием (разветвление индекса, ошибки INVALID_ARGUMENT), можно найти на странице устранения неполадок.