Poznawanie wydajności zapytań za pomocą funkcji Query Explain

Funkcja Query Explain umożliwia przesyłanie Cloud Firestore zapytań do backendu i otrzymywanie w zamian szczegółowych statystyk wydajności dotyczących wykonywania zapytań w backendzie. Działa podobnie jak operacja EXPLAIN [ANALYZE] w wielu systemach relacyjnych baz danych.

Żądania wyjaśnienia zapytania można wysyłać za pomocą bibliotek klienta serwera Firestore.

Wyniki wyjaśnienia zapytania pomagają zrozumieć, jak są wykonywane zapytania, pokazując nieefektywności i lokalizację prawdopodobnych wąskich gardeł po stronie serwera.

Wyjaśnienie zapytania:

  • Zawiera statystyki dotyczące fazy planowania zapytań, dzięki czemu możesz dostosować indeksy zapytań i zwiększyć wydajność.
  • Opcja analizy pomaga zrozumieć koszty i skuteczność poszczególnych zapytań oraz umożliwia szybkie iterowanie różnych wzorców zapytań w celu optymalizacji ich wykorzystania.

Omówienie opcji wyjaśniania zapytań: domyślnej i analizy

Operacje wyjaśniania zapytań można wykonywać za pomocą opcji domyślnej lub analizy.

W przypadku opcji domyślnej funkcja Query Explain planuje zapytanie, ale pomija etap wykonania. Spowoduje to zwrócenie informacji o etapie planowania. Możesz użyć tej funkcji, aby sprawdzić, czy zapytanie ma niezbędne indeksy, i dowiedzieć się, które indeksy są używane. Pomoże Ci to na przykład sprawdzić, czy dane zapytanie korzysta z indeksu złożonego, zamiast przecinać wiele różnych indeksów.

W przypadku opcji analizy funkcja Query Explain planuje i wykonuje zapytanie. Zwraca to wszystkie wspomniane wcześniej informacje o planerze wraz ze statystykami z czasu wykonywania zapytania. Będą one zawierać informacje rozliczeniowe dotyczące zapytania oraz statystyki na poziomie systemu dotyczące jego wykonania. Za pomocą tych narzędzi możesz testować różne konfiguracje zapytań i indeksów, aby zoptymalizować ich koszt i opóźnienie.

Ile kosztuje funkcja Wyjaśnienie zapytania?

Gdy używasz funkcji Wyjaśnij zapytanie z opcją domyślną, nie są wykonywane żadne operacje indeksowania ani odczytu. Niezależnie od złożoności zapytania naliczana jest opłata za 1 operację odczytu.

Jeśli używasz funkcji Query Explain z opcją analizy, wykonywane są operacje indeksowania i odczytu, więc zapłacisz za zapytanie jak zwykle. Za analizę nie są naliczane żadne dodatkowe opłaty. Obowiązuje tylko zwykła opłata za wykonywane zapytanie.

Używanie funkcji Wyjaśnij zapytanie z opcją domyślną

Aby przesłać prośbę o opcję domyślną, możesz użyć bibliotek klienta.

Pamiętaj, że żądania są uwierzytelniane za pomocą IAM przy użyciu tych samych uprawnień co w przypadku zwykłych operacji zapytań. Inne techniki uwierzytelniania, takie jak Firebase Authentication, są ignorowane. Więcej informacji znajdziesz w przewodniku IAM w przypadku bibliotek klienta serwera.

Java (administrator)

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

    
Węzeł (administrator)

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;

    

Dokładny format odpowiedzi zależy od środowiska wykonawczego. Zwrócone wyniki można przekonwertować na format JSON. Przykład:

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

Więcej informacji znajdziesz w materiałach referencyjnych do raportu Wyjaśnienie zapytania.

Korzystanie z funkcji Wyjaśnij zapytanie z opcją analizy

Za pomocą bibliotek klienta możesz przesyłać żądania opcji analizy.

Pamiętaj, że żądania są uwierzytelniane za pomocą IAM przy użyciu tych samych uprawnień co w przypadku zwykłych operacji zapytań. Inne techniki uwierzytelniania, takie jak Firebase Authentication, są ignorowane. Więcej informacji znajdziesz w przewodniku IAM w przypadku bibliotek klienta serwera.

Java (administrator)

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

    
Węzeł (administrator)

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;

    

Poniższy przykład pokazuje obiekt stats zwrócony oprócz planInfo. Dokładny format odpowiedzi zależy od środowiska wykonawczego. Przykładowa odpowiedź jest w formacie 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",
               }
    }

}

Więcej informacji znajdziesz w materiałach referencyjnych do raportu Wyjaśnienie zapytania.

Interpretowanie wyników i wprowadzanie zmian

Przyjrzyjmy się przykładowemu scenariuszowi, w którym wysyłamy zapytanie o filmy według gatunku i kraju produkcji.

Na przykład załóżmy, że masz zapytanie SQL podobne do tego.

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

Jeśli użyjemy opcji analizy, zwrócone dane pokażą, że zapytanie jest wykonywane na 2 indeksach z 1 polem: (category ASC, __name__ ASC)(country ASC, __name__ ASC). Skanuje 16 500 wpisów w indeksie, ale zwraca tylko 1200 dokumentów.

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

Aby zoptymalizować wydajność wykonywania zapytania, możesz utworzyć w pełni pokryty indeks złożony (category ASC, country ASC, __name__ ASC).

Ponowne uruchomienie zapytania z opcją analizy pokazuje, że dla tego zapytania wybrano nowo utworzony indeks, a samo zapytanie działa znacznie szybciej i wydajniej.

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