В этом разделе описывается индексирование для версии Firestore Enterprise. Firestore Enterprise не создает индексы по умолчанию. Чтобы снизить расходы и повысить производительность базы данных, создайте индексы для наиболее часто используемых запросов.
Индексы оказывают большое влияние на производительность базы данных. Если для запроса существует индекс, база данных может эффективно возвращать результаты, сокращая объем данных, которые необходимо сканировать, и сокращая работу, необходимую для сортировки результатов. Однако записи индекса увеличивают затраты на хранение и объем работы, выполняемой во время операции записи в индексированных полях.
Определение и структура индекса
Индекс состоит из следующих элементов:
- идентификатор подборки;
- список полей в заданной коллекции
- режим индекса (по возрастанию, по убыванию или array-contains) для каждого поля;
Индекс также может включать параметры sparse или unique.
Порядок индекса
Порядок и направление сортировки каждого поля однозначно определяют индекс. Например, следующие индексы являются разными и не взаимозаменяемы:
| Коллекция | Поля |
|---|---|
| города | страна (по возрастанию), население (по убыванию) |
| города | население (по убыванию), страна (по возрастанию), |
При создании индекса для поддержки запроса включите поля в том же порядке, что и в запросе.
Плотность индекса
По умолчанию в записях индекса хранятся данные из всех документов в коллекции. Такой индекс называется неразреженным. Запись в индексе будет добавлена для документа независимо от того, содержит ли он какие-либо поля, указанные в индексе. При создании записей индекса несуществующие поля обрабатываются как имеющие значение NULL. Чтобы изменить это поведение, вы можете определить индекс как разреженный.
Разреженные индексы
Разреженный индекс индексирует только те документы в коллекции, которые содержат значение (включая null) хотя бы для одного из индексированных полей. Разреженный индекс позволяет снизить расходы на хранение и повысить производительность.
Индексы array-contains
Чтобы оптимизировать производительность запросов при запросе поля массива с помощью array-contains или array-contains-any, вы можете проиндексировать поле в режиме array-contains. В индексе может быть не более одного поля в режиме array-contains.
Индексируя поле массива в режиме array-contains, механизм запросов может быстро находить документы, содержащие определенные значения массива. Без индекса запросы проверяют значения массива, выполняя полное сканирование коллекции, что увеличивает задержки запросов и затраты на чтение по мере роста размера коллекции.
Чтобы проиндексировать поле массива, оно должно соответствовать следующему требованию:
- Требование к непустому массиву. Запись индекса создается, только если поле массива существует в документе и является непустым массивом. Документы с отсутствующими, не являющимися массивами или пустыми полями массивов не индексируются.
Как плотность связана с индексами array-contains
Для индексов, включающих поле array-contains, правила плотности индексов применяются только к упорядоченным индексированным полям. Если требование о непустом массиве выполнено, правила плотности применяются к остальным упорядоченным индексированным полям в индексе:
- Неразреженный индекс (
DENSE). Для документа создается запись индекса. Все отсутствующие упорядоченные индексированные поля хранятся в записи индекса какnull. - Разреженный индекс (
SPARSE). Запись индекса создается, только если в документе есть хотя бы одно из упорядоченных индексированных полей.
Пример: создание записи индекса
Рассмотрим индекс users (tags[*], status ASC):
| Документ | Индекс NON-SPARSE |
Индекс SPARSE |
|---|---|---|
{ |
Проиндексировано: • (теги: "news", статус: "active") |
Проиндексировано: • (теги: "news", статус: "active") |
{ |
Проиндексировано: • (теги: "news", статус: "active") • (теги: "sports", статус: "active") |
Проиндексировано: • (теги: "news", статус: "active") • (теги: "sports", статус: "active") |
{ |
Проиндексировано: • (теги: "news", статус: "active") (дубликаты удалены) |
Проиндексировано: • (теги: "news", статус: "active") (дедуплицировано) |
{ |
Проиндексировано: • (теги: null, статус: "active") |
Проиндексировано: • (теги: null, статус: "active") |
{ |
Проиндексировано: • (теги: "news", статус: null) |
Не проиндексировано (отсутствует поле status) |
{ |
Не индексируется (поле не является массивом) | Не индексируется (поле не является массивом) |
{ |
Не индексируется (поле не является массивом) | Не индексируется (поле не является массивом) |
{ |
Не проиндексировано (отсутствует поле tags) |
Не проиндексировано (отсутствует поле tags) |
{ |
Не проиндексировано (пустой массив) | Не проиндексировано (пустой массив) |
Пример запроса
Веб-приложение
// Query for users where 'tags' contains 'news' and 'status' is 'active' const query = db.collection("users") .where("tags", "array-contains", "news") .where("status", "==", "active"); // Documents returned by the query: // [ // { // "id": "alice", // "tags": ["news", "tech"], // "status": "active" // } // ]
Уникальные индексы
Установите параметр уникального индекса, чтобы обеспечить уникальные значения для индексированных полей. Для индексов по нескольким полям каждая комбинация значений должна быть уникальной в пределах индекса. База данных отклоняет любые операции обновления и вставки, которые пытаются создать записи индекса с повторяющимися значениями. Если данные индексируемых полей содержат повторяющиеся значения и вы попытаетесь создать уникальный индекс, то его создание завершится ошибкой, сообщение о которой появится в сведениях об операции.
Отсутствующие поля в уникальном индексе
Если вы вставите документ с отсутствующими полями для уникального индекса, индекс установит значения null для отсутствующих полей. Полученная запись индекса должна быть уникальной, иначе операция завершится ошибкой.
Например, для этого индекса:
| Коллекция | Проиндексированные поля | Область действия запроса |
|---|---|---|
| города | название (по возрастанию); | Коллекция |
Если вы добавите в коллекцию документ {"abbreviation": "LA"}, уникальный индекс создаст запись, в которой для поля name будет задано значение null. Если вы попытаетесь добавить документ {"abbreviation": "NYC"}, операция не будет выполнена, поскольку результирующая запись для уникального индекса будет такой же.
То же самое относится к уникальным индексам с несколькими полями.
При создании или обновлении документа отсутствующие индексированные поля получают значение null, а полученная запись индекса должна быть уникальной в индексе.
Уникальные индексы для значений массива
Уникальный индекс array-contains запрещает документы с перекрывающимися элементами массива.
Этот тип индекса не требует, чтобы массив содержал уникальные значения в пределах одного документа.
Например, если у вас есть уникальный индекс для поля tags:
Допустимый документ doc1:
{
"tags": [ "news", "tech", "news", "music" ]
}
Индекс допускает повторяющиеся значения ("news") в одном массиве одного документа.
Если вы попытаетесь вставить второй документ doc2 с повторяющимся элементом, операция завершится ошибкой:
{
"tags": [ "sports", "music" ]
}
Операция не выполняется, поскольку "music" уже присутствует в массиве doc1 и сопоставлен в индексе.
Если вам нужно обеспечить уникальность элементов в одном массиве в одном документе, реализуйте это в логике приложения.
Пустые массивы, отсутствующие поля и нулевые значения
Обычно отсутствующие поля в уникальном индексе обрабатываются как null и должны быть уникальными для всех документов (см. раздел Отсутствующие поля в уникальном индексе).
Однако для уникальных индексов в полях массивов:
- Пустые массивы, отсутствующие поля и отдельные значения null. Если поле массива пустое, отсутствует или содержит отдельное значение
null(не внутри массива), ключи индекса для документа не генерируются. Поэтому несколько документов могут иметь пустые поля или отдельные значенияnull, не вызывая ошибок дублирования ключей. - Нулевые элементы в массиве. Если массив содержит элемент
со значением
null(например,["news", null]), то этотnullэлемент индексируется. Любой последующий документ, содержащий элементnullв поле индексированного массива, будет отклонен с ошибкой дублирования ключа.
Устранение ошибок при создании индекса
При управлении индексами могут возникать ошибки. Операция индексирования может завершиться ошибкой, если в базе данных возникнет проблема с данными. Операции индексирования могут завершаться ошибкой по следующим причинам:
- Достигнут лимит индекса. Например, возможно, достигнуто максимальное количество записей индекса на документ. Если создать индекс не удастся, вы увидите сообщение об ошибке. Если лимит не достигнут, повторите операцию индексирования.
- Вы установили параметр уникального индекса, и данные индексированных полей создадут повторяющиеся записи индекса. Чтобы продолжить, удалите повторяющиеся комбинации значений из данных.
Дальнейшие действия
Подробнее о том, как создавать индексы и управлять ими…