Einführung in Query Insights for Cloud SQL

1. Hinweis

Mit Query Insights for Cloud SQL können Sie Probleme mit der Abfrageleistung von Cloud SQL-Datenbanken erkennen, diagnostizieren und vermeiden. Die Lösung bietet Self-Service-Monitoring und Diagnoseinformationen, die über die Erkennung hinausgehen und Ihnen helfen, die Ursache von Leistungsproblemen zu ermitteln.

In diesem Codelab erfahren Sie, wie Sie eine Cloud SQL for PostgreSQL-Instanz einrichten, eine Node.js-Anwendung bereitstellen, um die Cloud SQL-Instanz als Back-End-Speicher zu verwenden, und dann mit Query Insights Abfragen aufrufen und überwachen.

Voraussetzungen

  • Grundkenntnisse der Programmiersprache und der Tools von Node.js

Aufgabe

  • Cloud SQL in einer Node.js-Anwendung verwenden
  • SQL Commenter in einer Node.js-Anwendung aktivieren
  • Mit Query Insights for Cloud SQL die Abfrageleistung überwachen und untersuchen

Voraussetzungen

  • Ein Google Cloud-Konto, mit dem Sie APIs aktivieren und Dienste erstellen können

2. Einrichtung und Anforderungen

Umgebung für das selbstbestimmte Lernen einrichten

  1. Melden Sie sich in der Cloud Console an und erstellen Sie ein neues Projekt oder verwenden Sie ein vorhandenes Projekt. Wenn Sie noch kein Gmail- oder Google Workspace-Konto haben, müssen Sie eines erstellen.

Merken Sie sich die Projekt-ID des von Ihnen verwendeten Projekts. Sie wird in diesem Codelab später als PROJECT-ID bezeichnet.

  1. Als Nächstes müssen Sie in der Cloud Console die Abrechnung aktivieren, um Google Cloud-Ressourcen nutzen zu können.

Dieses Codelab sollte möglichst wenig kosten. Folgen Sie der Anleitung unter "Bereinigen und Weitere Informationen". , in dem Sie erfahren, wie Sie Ressourcen herunterfahren, damit Ihnen über dieses Tutorial hinaus keine Kosten entstehen. Neue Google Cloud-Nutzer können an einem kostenlosen Testzeitraum mit 300$Guthaben teilnehmen.

Cloud Shell aktivieren

  1. Klicken Sie in der Cloud Console auf Cloud Shell aktivieren:

Cloud Shell aktivieren

Wenn Sie Cloud Shell zum ersten Mal verwenden, wird ein Zwischenbildschirm (below the fold) angezeigt, in dem beschrieben wird, worum es sich dabei handelt. Klicken Sie in diesem Fall auf Weiter. Der Chat wird nie wieder angezeigt. So sieht dieser einmalige Bildschirm aus:

Cloud Shell-Dialogfenster

Die Bereitstellung und Verbindung mit Cloud Shell dauert nur einen Moment.

Cloud Shell-Terminal

Diese virtuelle Maschine verfügt über sämtliche Entwicklertools, die Sie benötigen. Es bietet ein Basisverzeichnis mit 5 GB nichtflüchtigem Speicher und wird in Google Cloud ausgeführt. Dadurch werden die Netzwerkleistung und die Authentifizierung erheblich verbessert.

  1. Führen Sie in Cloud Shell den folgenden Befehl aus, um zu prüfen, ob Sie das richtige Projekt verwenden:

Sobald Sie mit Cloud Shell verbunden sind, sollten Sie sehen, dass Sie bereits authentifiziert sind und dass das Projekt bereits auf Ihre Projekt-ID eingestellt ist.

Führen Sie den folgenden Befehl aus, um zu prüfen, ob Sie das richtige Projekt verwenden.

gcloud config list project

Wenn Sie ein anderes Projekt als das verwenden möchten, das Sie beim Öffnen von Cloud Shell ausgewählt haben, können Sie mit dem folgenden Befehl ein neues Projekt einrichten:

gcloud config set project <PROJECT-ID>;

3. Cloud SQL for PostgreSQL-Instanz mit aktiviertem Query Insights einrichten

  1. Nach dem Start von Cloud Shell können Sie mit der Befehlszeile eine neue Cloud SQL-Instanz mit dem Namen my-instance mit aktiviertem Query Insights erstellen:
gcloud sql instances create my-instance --tier db-f1-micro --database-version=POSTGRES_12 --region=us-central --root-password=<PASSWORD> --insights-config-query-insights-enabled --insights-config-record-application-tags --insights-config-record-client-address

Hier finden Sie eine kurze Erklärung der Flags und ihrer Bedeutung:

  • Das Flag --tier db-f1-micro gibt einen Maschinentyp mit minimalen Ressourcen an, da dies zu Entwicklungszwecken dient und Sie nicht viele Ressourcen für das Codelab benötigen. Weitere Informationen zu Stufen
  • Das Flag --database-version=POSTGRES_12 erstellt eine Instanz der PostgreSQL-Version 12.
  • Das Flag --region=us-central gibt die Region an, in der die Instanz erstellt wird.
  • Mit dem Flag --root-password=<PASSWORD> können Sie das Passwort für den postgres-Root-Nutzer angeben. Ersetzen Sie <PASSWORD> durch ein Passwort Ihrer Wahl.
  • Das Flag --insights-config-query-insights-enabled aktiviert Query Insights für Ihre Instanz.
  • Mit dem Flag --insights-config-record-application-tags können Anwendungs-Tags aufgezeichnet werden. In späteren Abschnitten erfahren Sie mehr über Anwendungs-Tags.
  • Mit dem Flag --insights-config-record-client-address können Client-IP-Adressen von Query Insights aufgezeichnet werden.

Möglicherweise werden Sie aufgefordert, die API sqladmin.googleapis.com für Ihr Projekt zu aktivieren. Wenn Sie dazu aufgefordert werden, wählen Sie y aus, um die API zu aktivieren.

Das Erstellen der Instanz dauert einige Minuten. Sobald dieser Vorgang abgeschlossen ist, kann die Instanz verwendet werden.

  1. Erstellen Sie nun eine Datenbank, die Sie für die Beispielanwendung verwenden:
gcloud sql databases create votesdb --instance my-instance

Sie können die Instanz auch über die Cloud Console aufrufen und konfigurieren.

  1. Rufen Sie den Namen der Instanzverbindung im Format PROJECT-ID:ZONE-ID:INSTANCE-ID ab. Führen Sie dazu den folgenden Befehl aus. Sie benötigen ihn später bei der Konfiguration Ihrer Node.js-Anwendung.
gcloud sql instances describe my-instance | grep connectionName

4. Dienstkonto zur Verwendung mit der Anwendung erstellen

Dienstkonten werden verwendet, um Berechtigungen zur Verwendung verschiedener Dienste innerhalb Ihres GCP-Projekts zu erteilen. Für dieses Codelab benötigen Sie ein Codelab, um dem Cloud SQL-Proxy die Berechtigung zum Herstellen einer Verbindung zu Ihrer Cloud SQL-Instanz zu gewähren.

Dienstkonto in der Console erstellen

  1. Rufen Sie die IAM-Seite für Dienstkonten auf und klicken Sie oben auf der Seite auf die Schaltfläche -PCvKR3aQ2zKaUcml8w9lW4JNlmYtN5-r2--mC6kMUp6HOXW8wT1wUvLoYEPU-aA-oGskT3XkAqfNwRAKkZkllwTe6ugdrUVFwaeKT0M9Y1RwHA8JPZeGmCWYBfr8d9TSycNMIRsLw.
  2. Geben Sie Ihrem Dienstkonto einen eindeutigen Namen und eine eindeutige ID und klicken Sie auf ERSTELLEN.
  3. Klicke auf der nächsten Seite auf das Drop-down-Menü für „Rolle auswählen“. Nach „Cloud SQL“ filtern und wählen Sie die Rolle "Cloud SQL-Client" aus. Klicke auf WEITER und dann auf FERTIG.
  4. Klicken Sie nach dem Erstellen des Dienstkontos für Ihr neues Dienstkonto unter Aktionen auf das Dreipunkt-Menü und wählen Sie „Schlüssel verwalten“ aus. Wählen Sie auf der nächsten Seite SCHLÜSSEL HINZUFÜGEN und dann Neuen Schlüssel erstellen aus. „JSON“ wird ausgewählt. behalten Sie diese Standardeinstellung bei und klicken Sie auf ERSTELLEN. Dadurch wird eine private JSON-Schlüsseldatei heruntergeladen. Klicken Sie auf SCHLIEẞEN.
  5. Klicken Sie in Cloud Shell auf das Dreipunkt-Menü für das Dreipunkt-Menü und wählen Sie Datei hochladen aus. Wählen Sie die JSON-Datei aus, die Sie auf Ihren lokalen Computer heruntergeladen haben. Dadurch wird die JSON-Datei in Ihr Basisverzeichnis in Cloud Shell hochgeladen.

5. Cloud SQL-Proxy installieren und starten

Sie verwenden den Cloud SQL-Proxy für die Kommunikation zwischen der Anwendung und der Datenbankinstanz.

  1. Laden Sie den Cloud SQL-Proxy herunter. In Cloud Shell können Sie Folgendes ausführen:
wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 -O cloud_sql_proxy && chmod +x cloud_sql_proxy
  1. Führen Sie den Proxy so aus, nachdem Sie <INSTANCE_CONNECTION_NAME> durch den Namen der Instanzverbindung ersetzt haben, den Sie von der Übersichtsseite der Cloud SQL-Instanz kopiert haben.
./cloud_sql_proxy -instances=<INSTANCE_CONNECTION_NAME>=tcp:5432 &

Wenn dies gelingt, sollten Sie einige Ausgabezeilen sehen, die mit der Meldung Ready for new connections enden.

6. Anwendung lokal klonen und testen

  1. Klonen Sie das Repository für die Beispielanwendung und installieren Sie die Pakete, die zum Ausführen der App erforderlich sind.
git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples/

cd nodejs-docs-samples/cloud-sql/postgres/knex

npm install
  1. Legen Sie die folgenden Umgebungsvariablen fest:
export INSTANCE_CONNECTION_NAME='<PROJECT-ID>:<ZONE-ID>:<INSTANCE-ID>'
export DB_HOST='127.0.0.1:5432'
export DB_USER='postgres'
export DB_PASS='<PASSWORD>'
export DB_NAME='votesdb'
  1. Starten Sie die Beispiel-App.
npm start
  1. Klicken Sie in Cloud Shell auf WebvorschauSymbol für Webvorschau und wählen Sie dann Vorschau auf Port 8080 aus.

Menüpunkt „Vorschau auf Port 8080“

In Ihrem Browser sollte die Abstimmungs-App „Tabs vs. Gruppenbereiche“ angezeigt werden, wie hier gezeigt:

Screenshot der Abstimmungs-App „Tabs vs. Spaces“

  1. Klicken Sie auf die Schaltflächen, um Stimmen abzugeben und Daten in der Datenbank zu speichern.

7. Seite hinzufügen, um alle Stimmen zu sehen

Da diese Beispielanwendung sehr einfach ist, fügen Sie eine zusätzliche Seite hinzu, auf der alle Stimmen angezeigt werden. Der Hauptgrund dafür ist, dass Ihnen mehr Daten zur Verfügung stehen, wenn Sie Query Insights später verwenden.

  1. Geben Sie Ctrl+c in Cloud Shell ein, um die Beispielanwendung zu beenden.
  2. Klicken Sie in Cloud Shell auf die Schaltfläche Schaltfläche „Editor öffnen“, um den Cloud Shell-Editor zu starten.
  3. Suchen Sie im Datei-Explorer nach nodejs-docs-samples/cloud-sql/postgres/knex/server.js und klicken Sie darauf, um die Datei server.js in den Editor zu laden.

Fügen Sie dort, wo die Funktion getVotes definiert ist, den folgenden Code ein:

/**
 * Retrieve all vote records from the database.
 *
 * @param {object} pool The Knex connection object.
 * @returns {Promise}
 */
const getAllVotes = async pool => {
  return await pool
    .select('candidate', 'time_cast')
    .from('votes')
    .orderBy('time_cast', 'desc');
};
  1. Fügen Sie unten den folgenden Code für die Route '/getAllVotes' ein, wo die anderen Routen definiert sind:
app.get('/getAllVotes', async (req, res) => {
  pool = pool || createPool();
  try {
    // Query all votes from the database.
    const votes = await getAllVotes(pool);

    res.render('allvotes.pug', {
      votes: votes,
    });
  } catch (err) {
    console.error(err);
    res
      .status(500)
      .send('Unable to load page; see logs for more details.')
      .end();
  }
});
  1. Erstellen Sie im Verzeichnis nodejs-docs-samples/cloud-sql/postgres/knex/views eine neue Datei mit dem Namen allvotes.pug. Fügen Sie den folgenden Code ein:
doctype html
html(lang="en")
  head
    title Tabs VS Spaces

    link(rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css")
    link(rel="stylesheet", href="https://fonts.googleapis.com/icon?family=Material+Icons")
    script(src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js")
  body

    nav(class="red lighten-1")
      div(class="nav-wrapper")
        a(href="#" class="brand-logo center") Tabs VS Spaces

    div(class="section")

      h4(class="header center") Recent Votes
      ul(class="container collection center")
        each vote in votes
          li(class="collection-item avatar")
            if vote.candidate.trim() === 'TABS'
              i(class="material-icons circle green") keyboard_tab
            else
              i(class="material-icons circle blue") space_bar
            span(class="title") A vote for <b>#{vote.candidate}</b>
            p was cast at #{vote.time_cast}.
  1. Klicken Sie auf die Schaltfläche Schaltfläche „Terminal öffnen“, um zu Cloud Shell zurückzukehren und folgenden Befehl auszuführen:
npm start
  1. Öffne die App über die Webvorschau, um zu prüfen, ob sie funktioniert. Fügen Sie der URL im Browser /getAllVotes hinzu, um die neu hinzugefügte Seite zu sehen.

8. SQL Commenter in der App aktivieren

Als Nächstes installieren und aktivieren Sie SQL Commenter, eine Open-Source-Bibliothek, mit der ORMs SQL-Anweisungen vor der Ausführung mit Kommentaren erweitern können. SQLcommenter unterstützt mehrere ORMs und Frameworks, darunter das von der Beispiel-App verwendete Knex.js. Anhand der Informationen aus diesen Kommentaren bietet Query Insights einen anwendungsorientierten Einblick in die Datenbankleistung und ermittelt, welcher Anwendungscode Probleme verursacht. Der Leistungsaufwand ist voraussichtlich gering. Weitere Informationen finden Sie in der Dokumentation zu Query Insights.

  1. Geben Sie Ctrl+c in Cloud Shell ein, um die Beispielanwendung zu beenden.
  2. Führen Sie den folgenden Befehl aus, um die von SQLcommenter benötigten Pakete zu installieren:
  npm install @google-cloud/sqlcommenter-knex @opencensus/nodejs @opencensus/propagation-tracecontext @opentelemetry/api @opentelemetry/core --save
  1. Klicken Sie in Cloud Shell auf die Schaltfläche Schaltfläche „Editor öffnen“, um den Cloud Shell-Editor zu starten.
  2. Suchen Sie im Datei-Explorer nach nodejs-docs-samples/cloud-sql/postgres/knex/server.js und klicken Sie darauf, um die Datei server.js in den Editor zu laden.
  3. Sie finden diesen Code in der Datei:
const process = require('process');

Fügen Sie darunter den folgenden Code ein:

const {wrapMainKnexAsMiddleware} = require('@google-cloud/sqlcommenter-knex');
  1. Sie finden diesen Code in der Datei:
// Set Content-Type for all responses for these routes.
app.use((req, res, next) => {
  res.set('Content-Type', 'text/html');
  next();
});

Fügen Sie darunter den folgenden Code ein:

app.use(wrapMainKnexAsMiddleware(Knex, {
    traceparent: true,
    tracestate: true,
    route: true,
    db_driver: true
}));

Anschließend sollte Ihr Code in etwa so aussehen:

...
// Require process, so we can mock environment variables.
const process = require('process');

const {wrapMainKnexAsMiddleware} = require('@google-cloud/sqlcommenter-knex');
const express = require('express');
const Knex = require('knex');
const fs = require('fs');

const app = express();
app.set('view engine', 'pug');
app.enable('trust proxy');

// Automatically parse request body as form data.
app.use(express.urlencoded({extended: false}));
// This middleware is available in Express v4.16.0 onwards
app.use(express.json());

// Set Content-Type for all responses for these routes.
app.use((req, res, next) => {
  res.set('Content-Type', 'text/html');
  next();
});

app.use(wrapMainKnexAsMiddleware(Knex, {
    traceparent: true,
    tracestate: true,
    route: true,
    db_driver: true
}));
...
  1. Klicken Sie auf die Schaltfläche Schaltfläche „Terminal öffnen“, um zu Cloud Shell zurückzukehren und folgenden Befehl auszuführen:
npm start
  1. Klicken Sie in der Anwendung „Tabs im Vergleich zu Gruppenbereichen“ auf die Schaltflächen, um weitere Stimmen abzugeben und der Datenbank mehr Daten hinzuzufügen.

9. Mit Insights die Abfrageleistung und End-to-End-Tracing ansehen

Mit dem Query Insights-Dashboard können Sie Fehler in Cloud SQL-Abfragen beheben, um Leistungsprobleme zu erkennen. Um auf Insights zuzugreifen, wählen Sie im linken Navigationsbereich für Ihre Cloud SQL-Instanz Abfragestatistiken aus.

Datenbanklast – Grafik zu allen Abfragen

Das Dashboard der obersten Ebene für Query Insights zeigt das Diagramm Datenbanklast – alle Abfragen.

Grafik „Alle Abfragen“

Das Diagramm enthält Informationen zu CPU-Kapazität, CPU- und CPU-Wartezeit, E/A-Wartezeit und Sperrwartezeit. In der Dokumentation finden Sie weitere Informationen dazu, was diese Messwerte bedeuten und wo sie gespeichert werden. Außerdem finden Sie Beispiele dafür, wie diese Grafik bei problematischen Abfragen aussieht. Im Fall dieser Beispielanwendung ist die Datenbankabfragelast gering, sodass im Diagramm keine großen Spitzen zu sehen sind.

Welche Abfragen sind für die stärkste Auslastung verantwortlich?

Unter dem Diagramm befindet sich die Tabelle SUCHANFRAGEN, die die normalisierten Abfragen für den ausgewählten Zeitraum enthält. Die Abfragen in der Tabelle werden nach der Gesamtausführungszeit sortiert.

Tabelle mit den häufigsten Suchanfragen

Sie können auf eine einzelne Abfrage klicken, um detaillierte Informationen zu dieser Abfrage aufzurufen, z. B. die Datenbanklast für diese bestimmte Abfrage, die Abfragelatenz, Beispiele für Abfragepläne und Top-Nutzer. Wenn eine Anwendung mithilfe eines ORM erstellt wird, wie es bei der Beispielanwendung der Fall ist, wissen Sie möglicherweise nicht, welcher Teil der Anwendung für welche Abfrage verantwortlich ist. Im Abschnitt "Top-Tags" können Sie dies herausfinden.

Woher stammt die Abfragelast in der Anwendung?

Wechseln Sie von der Tabelle „QUERIES“ zur Tabelle „TAGS“, um eine Liste der Abfragen aufzurufen, die nach Geschäftslogik getaggt sind. So erhalten Sie eine stärker auf die Anwendung fokussierte Ansicht.

Tabelle mit Top-Tags

In der Tabelle TAGS wird die Datenbanklast aufgeschlüsselt nach der Route angezeigt, die sie generiert hat. Im Screenshot oben sehen Sie, dass die Route '/getAllVotes' eine höhere durchschnittliche Ausführungszeit hat und im Durchschnitt mehr Zeilen zurückgegeben hat. Obwohl die Ausführungszeit in der Tabelle in diesem Fall nicht problematisch ist, klicken wir trotzdem auf die Zeile für '/getAllVotes', um die Daten genauer anzusehen.

Warum werden Abfragen langsam ausgeführt?

Klicken Sie auf den Punkt im Diagramm Beispiele für Abfragepläne, um einen Abfrageplan aufzurufen.

Beispiele für Abfragepläne

Die Abfragepläne zeigen, wie PostgreSQL eine Abfrage ausführt. So lässt sich leichter feststellen, ob es Vorgänge gibt, die zu einer verlangsamten Ausführung führen.

Welcher Anwendungscode trägt zur langsamen Ausführung bei?

Query Insights bietet auch eine kontextbezogene Visualisierung des End-to-End-Tracings, die hilfreich sein kann, um genauer zu untersuchen, welche Teile einer Anwendung langsame Abfragen generieren.

Klicken Sie auf den Tab END TO END (Ende bis Ende), um einen Trace im Kontext anzusehen.

End-to-End-Trace

10. Bereinigen und mehr erfahren

Sie haben gelernt, wie Sie mithilfe von Query Insights die Abfrageleistung mit einer Node.js-Anwendung und einer PostgreSQL-Datenbank in Cloud SQL überwachen und untersuchen können.

Bereinigen

Wenn Sie Ihre Cloud SQL-Instanz nicht weiter ausführen möchten, können Sie sie jetzt löschen.

gcloud sql instances delete my-instance

Weitere Informationen