В этом разделе описывается индексирование для версии Firestore Enterprise. Firestore Enterprise не создает индексы по умолчанию. Чтобы снизить расходы и повысить производительность базы данных, создайте индексы для наиболее часто используемых запросов.
Индексы сильно влияют на производительность базы данных. Если для запроса существует индекс, база данных может эффективно возвращать результаты, сокращая объем данных, которые необходимо сканировать, и сокращая работу, необходимую для сортировки результатов. Однако записи индекса увеличивают затраты на хранение и объем работы, выполняемой во время операции записи в индексированных полях.
Определение и структура индекса
Индекс состоит из следующих элементов:
- идентификатор подборки;
- список полей в заданной коллекции
- режим индекса (по возрастанию, по убыванию или array-contains) для каждого поля;
Индекс также может включать параметры sparse или unique.
По индексу
Порядок и направление сортировки каждого поля однозначно определяют индекс. Например, следующие индексы являются разными и не взаимозаменяемы:
| Коллекция | Поля |
|---|---|
| города | страна (по возрастанию), население (по убыванию) |
| города | population (descending), country (ascending), |
При создании индекса для поддержки запроса включите поля в том же порядке, что и в запросе.
Плотность индекса
По умолчанию в записях индекса хранятся данные из всех документов в коллекции. Такой индекс называется неразреженным. Запись в индексе будет добавлена для документа независимо от того, содержит ли он какие-либо поля, указанные в индексе. При создании записей в индексе несуществующие поля обрабатываются как имеющие значение 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в поле индексированного массива, не будет обработан из-за ошибки дублирования ключа.
Устранение ошибок при создании индекса
При управлении индексами могут возникать ошибки. Операция индексирования может завершиться ошибкой, если в базе данных возникнет проблема с данными. Операции индексирования могут завершаться ошибкой по следующим причинам:
- Достигнут лимит индекса. Например, операция могла достичь максимального количества записей в индексе на документ. Если создать индекс не удастся, вы увидите сообщение об ошибке. Если лимит не достигнут, повторите операцию индексирования.
- Вы выбрали уникальный индекс, но данные индексируемых полей создадут повторяющиеся записи в индексе. Чтобы продолжить, удалите повторяющиеся комбинации значений из данных.
Дальнейшие действия
Подробнее о том, как создавать индексы и управлять ими…