На этой странице приведены примеры стратегии индексации, которую можно использовать для запросов с фильтрами диапазона и неравенства по нескольким полям для создания эффективного процесса запроса.
Прежде чем оптимизировать свои запросы, ознакомьтесь с сопутствующими концепциями .
Оптимизируйте запросы с помощью 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" } } }
Что дальше?
- Узнайте больше о Query Explain .
- Узнайте о лучших практиках индексации .