Индексы – важный фактор производительности базы данных. Подобно тому, как указатель книги сопоставляет темы в книге с номерами страниц, индекс базы данных сопоставляет элементы в базе данных с их местоположением в базе данных. Когда вы запрашиваете базу данных, она может использовать индекс, чтобы быстро определить местоположение запрашиваемых вами элементов.
На этой странице описаны два типа индексов, которые используются в 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")| Коллекция | Проиндексированные поля | Область действия запроса |
|---|---|---|
| города | страна, население | Коллекция |
| cities | страна, население | Коллекция |
Чтобы избежать снижения производительности, вызванного объединением индексов, рекомендуем создать индекс, который будет объединять запрос 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 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: {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), можно найти на странице устранения неполадок.