Entender o desempenho da consulta usando o Query Explain

O Query Explain permite enviar consultas do Firestore ao back-end e receber estatísticas detalhadas de desempenho sobre a execução de consultas de back-end em troca. Ela funciona como a operação EXPLAIN [ANALYZE] em muitas sistemas de bancos de dados relacionais.

As solicitações do Query Explain podem ser enviadas usando as bibliotecas de cliente do servidor do Firestore.

Os resultados do Query Explain ajudam a entender como suas consultas são executadas, mostrando ineficiências e a localização de possíveis incidentes os gargalos.

Explicação da consulta:

  • Fornece insights sobre a fase de planejamento da consulta para que você possa ajustar sua consulta índices e aumentar a eficiência.
  • O uso da opção de análise ajuda você a entender o custo e o desempenho em por consulta e permite acessar rapidamente diferentes tipos de personalizados para otimizar o uso deles.
.

Entender as opções de Query Explain: default e analyze

As operações do Query Explain podem ser executadas usando a opção default ou analyze.

Com a opção padrão, a explicação de consulta planeja a consulta, mas ignora no estágio de execução. Isso retornará informações do estágio do planejador. Você pode use isso para verificar se uma consulta tem os índices necessários e entender quais índices são usados. Isso o ajudará a verificar, por exemplo, se uma determinada consulta está usando um índice composto e ter de cruzar com muitas índices.

Com a opção de análise, a consulta explica os dois planos e executa o consulta. Isso retorna todas as informações do planejador mencionadas anteriormente, juntamente com estatísticas do ambiente de execução da consulta. Isso incluirá o faturamento Informações da consulta com insights no nível do sistema sobre a consulta em execução. É possível usar essas ferramentas para testar várias consultas e configurações para otimizar o custo e a latência.

Qual é o custo da Query Explain?

Quando você usa a opção Query Explain com a opção padrão, nenhuma índice ou operações de leitura são realizados. Independentemente da complexidade da consulta, uma operação de leitura é cobrada.

Quando você usa Query Explain com a opção de análise, índice e operações de leitura são realizadas, portanto, a consulta é cobrada normalmente. Não há nenhum valor adicional pela atividade de análise, apenas a cobrança normal pela consulta sendo executado.

Usar Query Explain com a opção padrão

Você pode usar as bibliotecas de cliente para enviar uma solicitação de opção padrão.

As solicitações são autenticadas com o IAM usando a mesma permissões para operações de consulta regulares. Outras técnicas de autenticação, como Firebase Authentication serão ignoradas. Para mais informações, consulte o guia sobre IAM para bibliotecas de cliente do servidor

Java (Admin)

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();

    
Nó (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;

    

O formato exato da resposta depende do ambiente de execução. Os resultados retornados podem ser convertidos em JSON. Exemplo:

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

Para mais informações, consulte a referência de relatório do Query Explain.

Usar o Query Explain com a opção de análise

Use as bibliotecas de cliente para enviar uma solicitação de opção de análise.

As solicitações são autenticadas com o IAM usando a mesma permissões para operações de consulta regulares. Outras técnicas de autenticação, como Firebase Authentication serão ignoradas. Para mais informações, consulte o guia sobre IAM para bibliotecas de cliente do servidor

Java (Admin)

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();

    
Nó (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;

    

O exemplo a seguir mostra o objeto stats retornado, além de planInfo. O formato exato da resposta depende do ambiente de execução. O exemplo de resposta está no 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 mais informações, consulte a referência de relatório do Query Explain.

Interpretar resultados e fazer ajustes

Vejamos um cenário de exemplo no qual consultamos filmes por gênero país de produção.

Para ilustração, suponha o equivalente desta consulta SQL.

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

Se usarmos a opção de análise, as métricas retornadas vão mostrar a consulta é executada em dois índices de campo único, (category ASC, __name__ ASC) e (country ASC, __name__ ASC). Ele verifica 16.500 entradas de índice, mas retorna somente 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 otimizar o desempenho da execução da consulta, crie um índice composto completamente coberto (category ASC, country ASC, __name__ ASC).

Ao executar a consulta com a opção de análise novamente, podemos ver um índice recém-criado é selecionado para essa consulta, e a consulta é executada muito mais rápido cada vez mais eficientes.

// 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",
               }
    }
}