Оптимизируйте запросы с помощью фильтров диапазона и неравенства в нескольких полях.

На этой странице приведены примеры стратегии индексации, которую можно использовать для запросов с фильтрами диапазона и неравенства по нескольким полям для создания эффективного процесса запроса.

Прежде чем оптимизировать свои запросы, ознакомьтесь с сопутствующими концепциями .

Оптимизируйте запросы с помощью Query Explain

Чтобы определить, оптимальны ли ваш запрос и индексы, вы можете использовать Query Explain для получения сводки плана запроса и статистики его выполнения:

Ява

Query q = db.collection("employees").whereGreaterThan("salary",
100000).whereGreaterThan("experience", 0);

ExplainResults<QuerySnapshot> explainResults = q.explain(ExplainOptions.builder().analyze(true).build()).get();
ExplainMetrics metrics = explainResults.getMetrics();

PlanSummary planSummary = metrics.getPlanSummary();
ExecutionStats executionStats = metrics.getExecutionStats();

System.out.println(planSummary.getIndexesUsed());
System.out.println(stats.getResultsReturned());
System.out.println(stats.getExecutionDuration());
System.out.println(stats.getReadOperations());
System.out.println(stats.getDebugStats());

Node.js

let q = db.collection("employees")
      .where("salary", ">", 100000)
      .where("experience", ">",0);

let options = { analyze : 'true' };
let explainResults = await q.explain(options);

let planSummary = explainResults.metrics.planSummary;
let stats = explainResults.metrics.executionStats;

console.log(planSummary);
console.log(stats);

В следующем примере показано, как использование правильного порядка индекса сокращает количество записей индекса, сканируемых Cloud Firestore .

Простые запросы

В предыдущем примере с коллекцией сотрудников простой запрос, который выполняется с индексом (experience ASC, salary ASC) выглядит следующим образом:

Ява

db.collection("employees")
  .whereGreaterThan("salary", 100000)
  .whereGreaterThan("experience", 0)
  .orderBy("experience")
  .orderBy("salary");

Запрос сканирует 95 000 записей индекса и возвращает всего пять документов. Поскольку предикат запроса не выполняется, большое количество записей индекса считывается, но отфильтровывается.

// Output query planning info
{
    "indexesUsed": [
        {
            "properties": "(experience ASC, salary ASC, __name__ ASC)",
            "query_scope": "Collection"
        }
    ],

    // Output Query Execution Stats
    "resultsReturned": "5",
    "executionDuration": "2.5s",
    "readOperations": "100",
    "debugStats": {
        "index_entries_scanned": "95000",
        "documents_scanned": "5",
        "billing_details": {
            "documents_billable": "5",
            "index_entries_billable": "95000",
            "small_ops": "0",
            "min_query_cost": "0"
        }
    }
}

Исходя из знаний предметной области, можно сделать вывод, что у большинства сотрудников есть хотя бы небольшой опыт работы, но лишь у немногих зарплата превышает 100 000. Учитывая это, можно заметить, что ограничение salary более избирательно, чем ограничение experience . Чтобы повлиять на индекс, используемый Cloud Firestore для выполнения запроса, укажите предложение orderBy , которое упорядочивает ограничение salary перед ограничением experience .

Ява

db.collection("employees")
  .whereGreaterThan("salary", 100000)
  .whereGreaterThan("experience", 0)
  .orderBy("salary")
  .orderBy("experience");

При явном использовании предложения orderBy() для добавления предикатов Cloud Firestore использует индекс (salary ASC, experience ASC) для выполнения запроса. Поскольку селективность первого фильтра диапазона в этом запросе выше, чем в предыдущем, запрос выполняется быстрее и экономичнее.

// Output query planning info
{
    "indexesUsed": [
        {
            "properties": "(salary ASC, experience ASC, __name__ ASC)",
            "query_scope": "Collection"
        }
    ],

    // Output Query Execution Stats
    "resultsReturned": "5",
    "executionDuration": "0.2s",
    "readOperations": "6",
    "debugStats": {
        "index_entries_scanned": "1000",
        "documents_scanned": "5",
        "billing_details": {
            "documents_billable": "5",
            "index_entries_billable": "1000",
            "small_ops": "0",
            "min_query_cost": "0"
        }
    }
}

Что дальше?