Comprende el rendimiento de las consultas con Query Explainer

Query Explainer te permite enviar consultas de Firestore al backend y recibir estadísticas de rendimiento detalladas sobre la ejecución de consultas de backend. Funciona como la operación EXPLAIN [ANALYZE] en muchos sistemas de bases de datos relacionales.

Las solicitudes de Query Explain se pueden enviar a través de las bibliotecas cliente del servidor de Firestore.

Los resultados de Query Explain te ayudan a comprender cómo se ejecutan tus consultas, lo que te muestra las ineficiencias y la ubicación de los posibles cuellos de botella del servidor.

Query Explain ayuda a lo siguiente:

  • Proporciona estadísticas sobre la fase de planificación de consultas para que puedas ajustar tus índices de consultas y aumentar la eficiencia.
  • Con la opción analyze, puedes comprender tus costos y rendimiento por consulta y te permite iterar rápidamente por medio de patrones de consulta para optimizar su uso.

Comprende las opciones de Query Explain: default y analyze

Las operaciones de Query Explain se pueden realizar con las opciones default o analyze.

Con la opción default, Query Explain planifica la consulta, pero omite la etapa de ejecución. Esto devolverá la información de la etapa del planificador. Puedes usar esta opción para verificar que una consulta tenga los índices necesarios y comprenda qué índices se usan. Esto te ayudará a verificar, por ejemplo, que una consulta específica use un índice compuesto en vez de intersectar varios índices distintos.

Con la opción analyze, Query Explain planifica y ejecuta la consulta. Esto devuelve toda la información del planificador mencionada anteriormente junto con estadísticas del tiempo de ejecución de las consultas. Esto incluirá los datos de facturación de la consulta junto con información a nivel del sistema de la ejecución de la consulta. Puedes usar estas herramientas para probar varias consultas y opciones de configuración de índices para optimizar el costo y la latencia.

¿Cuánto cuesta Query Explain?

Cuando usas Query Explain con la opción default, no se realizan operaciones de indexación ni de lectura. Sin importar la complejidad de la consulta, se cobra una sola operación de lectura.

Cuando usas Query Explain con la opción analyze, se realizan operaciones de indexación y de lectura, por lo que se te cobra la consulta como de costumbre. No hay cobros adicionales por la actividad de análisis, solo se cobra el cargo habitual por la consulta ejecutada.

Usa Query Explain con la opción default

Puedes usar las bibliotecas cliente para enviar una solicitud con la opción default.

Ten en cuenta que las solicitudes se autentican con IAM, a través de los mismos permisos para operaciones de consulta habituales. Otras técnicas de autenticación, como Firebase Authentication, se ignoran. Para obtener más información, consulta la guía sobre IAM para las bibliotecas cliente del servidor.

Java (Administrador)

Query q = db.collection("col").whereGreaterThan("a", 1);
ExplainOptions options = ExplainOptions.builder().build();

ExplainResults<QuerySnapshot> explainResults = q.explain(options).get();
ExplainMetrics metrics = explainResults.getMetrics();
PlanSummary planSummary = metrics.getPlanSummary();

    
Node (administrador)

const q = db.collection('col').where('country', '=', 'USA');
const options = { analyze : 'false' };

const explainResults = await q.explain(options);

const metrics = explainResults.metrics;
const plan = metrics.planSummary;

    

El formato exacto de la respuesta depende del entorno de ejecución. Los resultados que se muestran se pueden convertir a JSON. Por ejemplo:

{
    "indexes_used": [
        {"query_scope": "Collection", "properties": "(category ASC, __name__ ASC)"},
        {"query_scope": "Collection", "properties": "(country ASC, __name__ ASC)"},
    ]
}

Para obtener más información, consulta la referencia del informe de Query Explain.

Usa Query Explainer con la opción analyze

Puedes usar las bibliotecas cliente para enviar una solicitud de la opción analyze.

Ten en cuenta que las solicitudes se autentican con IAM, a través de los mismos permisos para operaciones de consulta habituales. Otras técnicas de autenticación, como Firebase Authentication, se ignoran. Para obtener más información, consulta la guía sobre IAM para las bibliotecas cliente del servidor.

Java (Administrador)

Query q = db.collection("col").whereGreaterThan("a", 1);

ExplainOptions options = ExplainOptions.builder().setAnalyze(true).build();

ExplainResults<QuerySnapshot> explainResults = q.explain(options).get();

ExplainMetrics metrics = explainResults.getMetrics();
PlanSummary planSummary = metrics.getPlanSummary();
List<Map<String, Object>> indexesUsed = planSummary.getIndexesUsed();
ExecutionStats stats = metrics.getExecutionStats();

    
Node (administrador)

const q = db.collection('col').where('country', '=', 'USA');

const options = { analyze : 'true' };

const explainResults = await q.explain(options);

const metrics = explainResults.metrics;
const plan = metrics.planSummary;
const indexesUsed = plan.indexesUsed;
const stats = metrics.executionStats;

    

En el siguiente ejemplo, se muestra el objeto stats que se devolvió además de planInfo. El formato exacto de la respuesta depende del entorno de ejecución. La respuesta del ejemplo está en formato JSON.

{
    "resultsReturned": "5",
    "executionDuration": "0.100718s",
    "readOperations": "5",
    "debugStats": {
               "index_entries_scanned": "95000",
               "documents_scanned": "5"
               "billing_details": {
                     "documents_billable": "5",
                     "index_entries_billable": "0",
                     "small_ops": "0",
                     "min_query_cost": "0",
               }
    }

}

Para obtener más información, consulta la referencia del informe de Query Explain.

Interpreta los resultados y haz ajustes

Veamos un ejemplo de situación en la que consultamos películas por género y país de producción.

A modo de ejemplo, supongamos el equivalente de esta consulta en SQL.

SELECT *
FROM /movies
WHERE category = 'Romantic' AND country = 'USA';

Si usamos la opción analyze, las métricas devueltas mostrarán que la consulta se ejecuta en dos índices de campo único, (category ASC, __name__ ASC) y (country ASC, __name__ ASC). Analiza 16,500 entradas de índice, pero devuelve solo 1,200 documentos.

// Output query planning info
{
    "indexes_used": [
        {"query_scope": "Collection", "properties": "(category ASC, __name__ ASC)"},
        {"query_scope": "Collection", "properties": "(country ASC, __name__ ASC)"},
    ]
}

// Output query status
{
    "resultsReturned": "1200",
    "executionDuration": "0.118882s",
    "readOperations": "1200",
    "debugStats": {
               "index_entries_scanned": "16500",
               "documents_scanned": "1200"
               "billing_details": {
                     "documents_billable": "1200",
                     "index_entries_billable": "0",
                     "small_ops": "0",
                     "min_query_cost": "0",
               }
    }
}

Para optimizar el rendimiento de la ejecución de la consulta, puedes crear un índice compuesto (category ASC, country ASC, __name__ ASC) completamente cubierto.

Si vuelves a ejecutar la consulta con la opción analyze, podemos ver que para esta consulta se selecciona un índice recién creado y la consulta se ejecuta mucho más rápido y de manera más eficiente.

// Output query planning info
{
    "indexes_used": [
        {"query_scope": "Collection", "properties": "(category ASC, country ASC,  __name__ ASC)"}
    ]
}

// Output query stats
{
    "resultsReturned": "1200",
    "executionDuration": "0.026139s",
    "readOperations": "1200",
    "debugStats": {
               "index_entries_scanned": "1200",
               "documents_scanned": "1200"
               "billing_details": {
                     "documents_billable": "1200",
                     "index_entries_billable": "0",
                     "small_ops": "0",
                     "min_query_cost": "0",
               }
    }
}