Abfrageoptimierung verwalten

Die Abfrageoptimierung von Cloud Spanner bestimmt die effizienteste Möglichkeit, eine SQL-Abfrage auszuführen. Der vom Optimierungstool festgelegte Abfrageplan kann sich jedoch geringfügig ändern, wenn sich die Abfrageoptimierung selbst entwickelt oder die Datenbankstatistiken aktualisiert werden. Cloud Spanner bietet die folgenden Abfrageoptionen, um das Risiko von Leistungsrückgängen bei der Änderung der Abfrageoptimierung oder Statistik zu minimieren.

  • optimize_version: Änderungen am Abfrageoptimierungstool sind gebündelt und als Optimierungstoolversionen verfügbar. Cloud Spanner verwendet die neueste Version des Optimierungstools mindestens 30 Tage nach Veröffentlichung dieser Version als Standard. Mit der Option der Abfrageoptimierungsversion können Sie Abfragen für eine ältere Version des Optimierungstools ausführen.

  • optimize_statistics_package: Die Statistiken des Optimierungstools werden von Cloud Spanner regelmäßig aktualisiert. Neue Statistiken werden als Paket verfügbar gemacht. Diese Abfrageoption gibt ein Statistikpaket für die Abfrageoptimierung an, das beim Kompilieren einer SQL-Abfrage verwendet werden soll. Für das angegebene Paket muss die automatische Speicherbereinigung deaktiviert sein:

    ALTER STATISTICS <package_name> SET OPTIONS (allow_gc=false)

In dieser Anleitung wird beschrieben, wie Sie diese einzelnen Optionen in verschiedenen Bereichen in Cloud Spanner festlegen.

Versionen von Abfrageoptionen auflisten

Cloud Spanner speichert Informationen zu den verfügbaren Optimierungsversionen und Statistikpaketen, die Sie auswählen können.

Optimierungsversionen

Die Abfrageoptimierungsversion ist ein ganzzahliger Wert, der bei jeder Aktualisierung um 1 erhöht wird. Die neueste Version der Abfrageoptimierung ist 3.

Führen Sie die folgende SQL-Anweisung aus, um eine Liste aller unterstützten Optimierungsversionen zusammen mit den entsprechenden Veröffentlichungsdaten und der Standardversion zurückzugeben. Die größte zurückgegebene Versionsnummer ist die neueste unterstützte Version des Optimierungstools.

SELECT * FROM SPANNER_SYS.SUPPORTED_OPTIMIZER_VERSIONS;

Standardversion

Standardmäßig verwendet Cloud Spanner mindestens 30 Tage nach Veröffentlichung der Version die neueste Version des Optimierungstools. Während eines Zeitraums von 30 Tagen zwischen einem neuen Release und diesem Release als Standard wird empfohlen, Abfragen der neuen Version zu testen, um etwaige Regressionen zu erkennen.

Führen Sie die folgende SQL-Anweisung aus, um die Standardversion zu ermitteln:

SELECT * FROM SPANNER_SYS.SUPPORTED_OPTIMIZER_VERSIONS`

Die Abfrage gibt eine Liste aller unterstützten Optimierungsversionen zurück. Die Spalte IS_DEFAULT gibt an, welche Version die aktuelle Standardeinstellung ist.

Weitere Informationen zu den einzelnen Versionen finden Sie unter Versionsverlauf des Abfrageoptimierungstools.

Optimierungstool-Statistikpakete

Jedem neuen Optimierungstool-Statistikpaket, das Cloud Spanner erstellt, wird ein Paketname zugewiesen, der garantiert innerhalb der angegebenen Datenbank eindeutig ist.

Führen Sie die folgende SQL-Anweisung aus, um eine Liste aller verfügbaren Optimierungstool-Statistikpakete zurückzugeben. Die einzelnen Paketnamen haben das Format auto_{PACKAGE_TIMESTAMP}UTC, wobei {PACKAGE_TIMESTAMP} der Zeitstempel in UTC-Zeitzone des Beginns der Statistikerfassung ist.

SELECT * FROM INFORMATION_SCHEMA.SPANNER_STATISTICS;

Standardmäßig verwendet Cloud Spanner das neueste Optimierungstool-Statistikpaket, es sei denn, die Datenbank oder Abfrage ist mit einer der auf dieser Seite beschriebenen Methoden an ein älteres Paket angepinnt.

Vorrang vor Optionen

Cloud Spanner bietet mehrere Möglichkeiten, die Optimierungsoptionen zu ändern. Sie können beispielsweise die Optionen für eine bestimmte Abfrage festlegen oder die Option in der Clientbibliothek auf Prozess- oder Abfrageebene konfigurieren. Wenn eine Option auf mehrere Arten festgelegt wird, gilt die folgende Prioritätsreihenfolge. Wählen Sie einen Link aus, um zu diesem Abschnitt in diesem Dokument zu springen.

Cloud Spanner-Standardeinstellung ← DatenbankoptionClient-AnwendungUmgebungsvariableClient-AbfrageAnweisungshinweis

So können Sie beispielsweise die Reihenfolge der Priorität beim Festlegen der Version des Abfrageoptimierungstools interpretieren:

Wenn Sie eine Datenbank erstellen, wird die standardmäßige Version des Cloud Spanner-Tools verwendet. Das Festlegen der Optimierungsversion mithilfe einer der oben aufgeführten Methoden hat Vorrang vor allen links davon. Wenn Sie beispielsweise das Optimierungstool für eine Anwendung mit einer Umgebungsvariable festlegen, hat dieser Vorrang vor allen Werten, die Sie mit der Datenbankoption für die Datenbank festlegen. aus. Das Festlegen der Optimierungsversion über einen Anweisungshinweis hat die höchste Priorität für die angegebene Abfrage und hat Vorrang vor dem Wert, der mit einer anderen Methode festgelegt wurde.

Sehen wir uns nun jede Methode genauer an.

Optimierungsoptionen auf Datenbankebene festlegen

Sie können die Standardoptimierungsversion einer Datenbank mit dem folgenden DDL-Befehl ALTER DATABASE festlegen.

ALTER DATABASE MyDatabase
SET OPTIONS (optimizer_version = 3);

Sie können das Statistikpaket ähnlich wie im folgenden Beispiel festlegen.

ALTER DATABASE MyDatabase
SET OPTIONS (optimizer_statistics_package = "auto_20191128_14_47_22UTC");

Sie können auch mehrere Optionen gleichzeitig festlegen, wie im folgenden DDL-Befehl gezeigt.

ALTER DATABASE MyDatabase
SET OPTIONS (optimizer_version = 3,
             optimizer_statistics_package = "auto_20191128_14_47_22UTC");

Sie können ALTER DATABASE in gcloud spanner mit dem Befehl gcloud spanner databases ddl update so ausführen:

gcloud spanner databases ddl update MyDatabase --instance=test-instance \
    --ddl='ALTER DATABASE MyDatabase SET OPTIONS ( optimizer_version = 3 )'

Wenn Sie eine Datenbankoption auf NULL festlegen, wird sie gelöscht, sodass der Standardwert verwendet wird.

Den aktuellen Wert dieser Optionen für eine Datenbank können Sie in der Ansicht INFORMATION_SCHEMA.DATABASE_OPTIONS abfragen.

SELECT
  s.OPTION_NAME,
  s.OPTION_VALUE
FROM
  INFORMATION_SCHEMA.DATABASE_OPTIONS s
WHERE
  s.SCHEMA_NAME=""
  AND s.OPTION_NAME IN ('optimizer_version', 'optimizer_statistics_package')

Optimierungsoptionen mit Cloud Spanner-Clientbibliotheken festlegen

Bei der programmatischen Interaktion mit Cloud Spanner über Clientbibliotheken gibt es eine Reihe von Möglichkeiten, die Abfrageoptionen für Ihre Clientanwendung zu ändern.

Sie müssen die neuesten Versionen der Clientbibliotheken verwenden, um Optimierungsoptionen festzulegen.

Optimierungsoptionen für einen Datenbankclient festlegen

Eine Anwendung kann Optimierungsoptionen global in der Clientbibliothek festlegen. Dazu konfiguriert sie das Attribut für Abfrageoptionen, wie in den folgenden Code-Snippets dargestellt. Die Einstellungen des Optimierungsprogramms werden in der Clientinstanz gespeichert und auf alle Abfragen angewendet, die während der gesamten Lebensdauer des Clients ausgeführt werden. Obwohl die Optionen auf einer Datenbankebene im Back-End gelten, gelten sie aber auf allen Clientebenen, die mit diesem Client verbunden sind, wenn die Optionen auf Clientebene festgelegt werden.

C++

namespace spanner = ::google::cloud::spanner;
spanner::Client client(
    spanner::MakeConnection(db),
    spanner::ClientOptions().set_query_options(
        spanner::QueryOptions()
            .set_optimizer_version("1")
            .set_optimizer_statistics_package("auto_20191128_14_47_22UTC")));

C#

var builder = new SpannerConnectionStringBuilder
{
    DataSource = $"projects/{projectId}/instances/{instanceId}/databases/{databaseId}"
};
// Create connection to Cloud Spanner.
using (var connection = new SpannerConnection(builder))
{
    // Set query options on the connection.
    connection.QueryOptions = QueryOptions.Empty
        .WithOptimizerVersion("1")
        .WithOptimizerStatisticsPackage("auto_20191128_14_47_22UTC");
    var cmd = connection.CreateSelectCommand(
        "SELECT SingerId, AlbumId, AlbumTitle FROM Albums");
    using (var reader = await cmd.ExecuteReaderAsync())
    {
        while (await reader.ReadAsync())
        {
            Console.WriteLine("SingerId : "
            + reader.GetFieldValue<string>("SingerId")
            + " AlbumId : "
            + reader.GetFieldValue<string>("AlbumId")
            + " AlbumTitle : "
            + reader.GetFieldValue<string>("AlbumTitle"));
        }
    }
}

Go


import (
	"context"
	"fmt"
	"io"
	"time"

	"cloud.google.com/go/spanner"
	"google.golang.org/api/iterator"
	sppb "google.golang.org/genproto/googleapis/spanner/v1"
)

func createClientWithQueryOptions(w io.Writer, database string) error {
	ctx := context.Background()
	queryOptions := spanner.QueryOptions{
		Options: &sppb.ExecuteSqlRequest_QueryOptions{
			OptimizerVersion: "1",
			// The list of available statistics packages can be found by
			// querying the "INFORMATION_SCHEMA.SPANNER_STATISTICS" table.
			OptimizerStatisticsPackage: "latest",
		},
	}
	client, err := spanner.NewClientWithConfig(
		ctx, database, spanner.ClientConfig{QueryOptions: queryOptions},
	)
	if err != nil {
		return err
	}
	defer client.Close()

	stmt := spanner.Statement{SQL: `SELECT VenueId, VenueName, LastUpdateTime FROM Venues`}
	iter := client.Single().Query(ctx, stmt)
	defer iter.Stop()
	for {
		row, err := iter.Next()
		if err == iterator.Done {
			return nil
		}
		if err != nil {
			return err
		}
		var venueID int64
		var venueName string
		var lastUpdateTime time.Time
		if err := row.Columns(&venueID, &venueName, &lastUpdateTime); err != nil {
			return err
		}
		fmt.Fprintf(w, "%d %s %s\n", venueID, venueName, lastUpdateTime)
	}
}

Java

static void clientWithQueryOptions(DatabaseId db) {
  SpannerOptions options =
      SpannerOptions.newBuilder()
          .setDefaultQueryOptions(
              db, QueryOptions
                  .newBuilder()
                  .setOptimizerVersion("1")
                  // The list of available statistics packages can be found by querying the
                  // "INFORMATION_SCHEMA.SPANNER_STATISTICS" table.
                  .setOptimizerStatisticsPackage("latest")
                  .build())
          .build();
  Spanner spanner = options.getService();
  DatabaseClient dbClient = spanner.getDatabaseClient(db);
  try (ResultSet resultSet =
      dbClient
          .singleUse()
          .executeQuery(Statement.of("SELECT SingerId, AlbumId, AlbumTitle FROM Albums"))) {
    while (resultSet.next()) {
      System.out.printf(
          "%d %d %s\n", resultSet.getLong(0), resultSet.getLong(1), resultSet.getString(2));
    }
  }
}

Node.js

// Imports the Google Cloud client library
const {Spanner} = require('@google-cloud/spanner');

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';

// Creates a client
const spanner = new Spanner({
  projectId: projectId,
});

// Gets a reference to a Cloud Spanner instance and database
const instance = spanner.instance(instanceId);
const database = instance.database(
  databaseId,
  {},
  {
    optimizerVersion: '1',
    // The list of available statistics packages can be found by querying the
    // "INFORMATION_SCHEMA.SPANNER_STATISTICS" table.
    optimizerStatisticsPackage: 'latest',
  }
);

const query = {
  sql: `SELECT AlbumId, AlbumTitle, MarketingBudget
        FROM Albums
        ORDER BY AlbumTitle`,
};

// Queries rows from the Albums table
try {
  const [rows] = await database.run(query);

  rows.forEach(row => {
    const json = row.toJSON();
    const marketingBudget = json.MarketingBudget
      ? json.MarketingBudget
      : null; // This value is nullable
    console.log(
      `AlbumId: ${json.AlbumId}, AlbumTitle: ${json.AlbumTitle}, MarketingBudget: ${marketingBudget}`
    );
  });
} catch (err) {
  console.error('ERROR:', err);
} finally {
  // Close the database when finished.
  database.close();
}

PHP

use Google\Cloud\Spanner\SpannerClient;
use Google\Cloud\Spanner\Database;

/**
 * Create a client with query options.
 * Example:
 * ```
 * create_client_with_query_options($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function create_client_with_query_options($instanceId, $databaseId)
{
    $spanner = new SpannerClient([
        'queryOptions' => [
            'optimizerVersion' => '1',
            // Pin the statistics package used for this client instance to the
            // latest version. The list of available statistics packages can be
            // found by querying the "INFORMATION_SCHEMA.SPANNER_STATISTICS"
            // table.
            'optimizerStatisticsPackage' => 'latest'
        ]
    ]);
    $instance = $spanner->instance($instanceId);
    $database = $instance->database($databaseId);

    $results = $database->execute(
        'SELECT VenueId, VenueName, LastUpdateTime FROM Venues'
    );

    foreach ($results as $row) {
        printf('VenueId: %s, VenueName: %s, LastUpdateTime: %s' . PHP_EOL,
            $row['VenueId'], $row['VenueName'], $row['LastUpdateTime']);
    }
}

Python

# instance_id = "your-spanner-instance"
# database_id = "your-spanner-db-id"
spanner_client = spanner.Client(
    query_options={
        "optimizer_version": "1",
        "optimizer_statistics_package": "auto_20191128_14_47_22UTC"
    })
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)

with database.snapshot() as snapshot:
    results = snapshot.execute_sql(
        "SELECT VenueId, VenueName, LastUpdateTime FROM Venues"
    )

    for row in results:
        print(u"VenueId: {}, VenueName: {}, LastUpdateTime: {}".format(*row))

Ruby

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"

require "google/cloud/spanner"

query_options = {
  optimizer_version: "1",
  # The list of available statistics packages can be
  # found by querying the "INFORMATION_SCHEMA.SPANNER_STATISTICS"
  # table.
  optimizer_statistics_package: "latest"
}

spanner = Google::Cloud::Spanner.new project: project_id
client  = spanner.client instance_id, database_id, query_options: query_options

sql_query = "SELECT VenueId, VenueName, LastUpdateTime FROM Venues"

client.execute(sql_query).rows.each do |row|
  puts "#{row[:VenueId]} #{row[:VenueName]} #{row[:LastUpdateTime]}"
end

Optimierungsoptionen mit Umgebungsvariablen festlegen

Damit Sie verschiedene Optimierungseinstellungen einfacher ausprobieren können, ohne die Anwendung neu kompilieren zu müssen, können Sie die Umgebungsvariablen SPANNER_OPTIMIZER_VERSION und SPANNER_OPTIMIZER_STATISTICS_PACKAGE festlegen und Ihre Anwendung wie unten gezeigt ausführen. ein.

Linux/macOS

export SPANNER_OPTIMIZER_VERSION="3"
export SPANNER_OPTIMIZER_STATISTICS_PACKAGE="auto_20191128_14_47_22UTC"

Windows

set SPANNER_OPTIMIZER_VERSION="3"
  set SPANNER_OPTIMIZER_STATISTICS_PACKAGE="auto_20191128_14_47_22UTC"

Die angegebenen Optionen der Abfrageoptimierungsoption werden während der Initialisierung des Clients in die Clientinstanz gelesen und gespeichert und gelten für alle Abfragen, die während der gesamten Lebensdauer des Clients ausgeführt werden.

Optimierungsoptionen für eine Clientabfrage festlegen

Sie können einen Wert für die Optimierungsversion oder das Statistikpaket auf Abfrageebene in Ihrer Clientanwendung angeben, indem Sie beim Erstellen Ihrer Abfrage ein Abfrageoptionen-Attribut angeben.

C++

void QueryWithQueryOptions(google::cloud::spanner::Client client) {
  namespace spanner = ::google::cloud::spanner;
  auto sql = spanner::SqlStatement("SELECT SingerId, FirstName FROM Singers");
  auto opts = spanner::QueryOptions()
                  .set_optimizer_version("1")
                  .set_optimizer_statistics_package("latest");
  auto rows = client.ExecuteQuery(std::move(sql), std::move(opts));

  using RowType = std::tuple<std::int64_t, std::string>;
  for (auto const& row : spanner::StreamOf<RowType>(rows)) {
    if (!row) throw std::runtime_error(row.status().message());
    std::cout << "SingerId: " << std::get<0>(*row) << "\t";
    std::cout << "FirstName: " << std::get<1>(*row) << "\n";
  }
  std::cout << "Read completed for [spanner_query_with_query_options]\n";
}

C#

var builder = new SpannerConnectionStringBuilder
{
    DataSource = $"projects/{projectId}/instances/{instanceId}/databases/{databaseId}"
};
// Create connection to Cloud Spanner.
using (var connection = new SpannerConnection(builder))
{
    var cmd = connection.CreateSelectCommand(
        "SELECT SingerId, AlbumId, AlbumTitle FROM Albums");
    // Set query options just for this command.
    cmd.QueryOptions = QueryOptions.Empty
        .WithOptimizerVersion("1")
        .WithOptimizerStatisticsPackage("latest");
    using (var reader = await cmd.ExecuteReaderAsync())
    {
        while (await reader.ReadAsync())
        {
            Console.WriteLine("SingerId : "
            + reader.GetFieldValue<string>("SingerId")
            + " AlbumId : "
            + reader.GetFieldValue<string>("AlbumId")
            + " AlbumTitle : "
            + reader.GetFieldValue<string>("AlbumTitle"));
        }
    }
}

Go


import (
	"context"
	"fmt"
	"io"
	"time"

	"cloud.google.com/go/spanner"
	"google.golang.org/api/iterator"
	sppb "google.golang.org/genproto/googleapis/spanner/v1"
)

func queryWithQueryOptions(w io.Writer, db string) error {
	ctx := context.Background()
	client, err := spanner.NewClient(ctx, db)
	if err != nil {
		return err
	}
	defer client.Close()

	stmt := spanner.Statement{SQL: `SELECT VenueId, VenueName, LastUpdateTime FROM Venues`}
	queryOptions := spanner.QueryOptions{
		Options: &sppb.ExecuteSqlRequest_QueryOptions{
			OptimizerVersion: "1",
			// The list of available statistics packages can be found by
			// querying the "INFORMATION_SCHEMA.SPANNER_STATISTICS" table.
			OptimizerStatisticsPackage: "latest",
		},
	}
	iter := client.Single().QueryWithOptions(ctx, stmt, queryOptions)
	defer iter.Stop()
	for {
		row, err := iter.Next()
		if err == iterator.Done {
			return nil
		}
		if err != nil {
			return err
		}
		var venueID int64
		var venueName string
		var lastUpdateTime time.Time
		if err := row.Columns(&venueID, &venueName, &lastUpdateTime); err != nil {
			return err
		}
		fmt.Fprintf(w, "%d %s %s\n", venueID, venueName, lastUpdateTime)
	}
}

Java

static void queryWithQueryOptions(DatabaseClient dbClient) {
  try (ResultSet resultSet =
      dbClient
          .singleUse()
          .executeQuery(
              Statement
                  .newBuilder("SELECT SingerId, AlbumId, AlbumTitle FROM Albums")
                  .withQueryOptions(QueryOptions
                      .newBuilder()
                      .setOptimizerVersion("1")
                      // The list of available statistics packages can be found by querying the
                      // "INFORMATION_SCHEMA.SPANNER_STATISTICS" table.
                      .setOptimizerStatisticsPackage("latest")
                      .build())
                  .build())) {
    while (resultSet.next()) {
      System.out.printf(
          "%d %d %s\n", resultSet.getLong(0), resultSet.getLong(1), resultSet.getString(2));
    }
  }
}

Node.js

// Imports the Google Cloud client library
const {Spanner} = require('@google-cloud/spanner');

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';

// Creates a client
const spanner = new Spanner({
  projectId: projectId,
});

// Gets a reference to a Cloud Spanner instance and database
const instance = spanner.instance(instanceId);
const database = instance.database(databaseId);

const query = {
  sql: `SELECT AlbumId, AlbumTitle, MarketingBudget
        FROM Albums
        ORDER BY AlbumTitle`,
  queryOptions: {
    optimizerVersion: 'latest',
    // The list of available statistics packages can be found by querying the
    // "INFORMATION_SCHEMA.SPANNER_STATISTICS" table.
    optimizerStatisticsPackage: 'latest',
  },
};

// Queries rows from the Albums table
try {
  const [rows] = await database.run(query);

  rows.forEach(row => {
    const json = row.toJSON();
    const marketingBudget = json.MarketingBudget
      ? json.MarketingBudget
      : null; // This value is nullable
    console.log(
      `AlbumId: ${json.AlbumId}, AlbumTitle: ${json.AlbumTitle}, MarketingBudget: ${marketingBudget}`
    );
  });
} catch (err) {
  console.error('ERROR:', err);
} finally {
  // Close the database when finished.
  database.close();
}

PHP

use Google\Cloud\Spanner\SpannerClient;
use Google\Cloud\Spanner\Database;

/**
 * Queries sample data using SQL with query options.
 * Example:
 * ```
 * query_data_with_query_options($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function query_data_with_query_options($instanceId, $databaseId)
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);
    $database = $instance->database($databaseId);

    $results = $database->execute(
        'SELECT VenueId, VenueName, LastUpdateTime FROM Venues',
        [
            'queryOptions' => [
                'optimizerVersion' => '1',
                // Pin the statistics package to the latest version just for
                // this query.
                'optimizerStatisticsPackage' => 'latest'
            ]
        ]
    );

    foreach ($results as $row) {
        printf('VenueId: %s, VenueName: %s, LastUpdateTime: %s' . PHP_EOL,
            $row['VenueId'], $row['VenueName'], $row['LastUpdateTime']);
    }
}

Python

# instance_id = "your-spanner-instance"
# database_id = "your-spanner-db-id"
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)

with database.snapshot() as snapshot:
    results = snapshot.execute_sql(
        "SELECT VenueId, VenueName, LastUpdateTime FROM Venues",
        query_options={
            "optimizer_version": "1",
            "optimizer_statistics_package": "latest"
        },
    )

    for row in results:
        print(u"VenueId: {}, VenueName: {}, LastUpdateTime: {}".format(*row))

Ruby

# project_id  = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"

require "google/cloud/spanner"

spanner = Google::Cloud::Spanner.new project: project_id
client  = spanner.client instance_id, database_id

sql_query = "SELECT VenueId, VenueName, LastUpdateTime FROM Venues"
query_options = {
  optimizer_version: "1",
  # The list of available statistics packagebs can be
  # found by querying the "INFORMATION_SCHEMA.SPANNER_STATISTICS"
  # table.
  optimizer_statistics_package: "latest"
}

client.execute(sql_query, query_options: query_options).rows.each do |row|
  puts "#{row[:VenueId]} #{row[:VenueName]} #{row[:LastUpdateTime]}"
end

Optimierungsoptionen für eine Abfrage mit einem Anweisungshinweis festlegen

Ein Anweisungshinweis ist ein Hinweis auf eine Abfrageanweisung, durch den die Ausführung der Abfrage vom Standardverhalten abweicht. Wenn Sie den OPTIMIZER_VERSION-Hinweis für eine Anweisung festlegen, wird die Ausführung der Abfrage mit der angegebenen Version des Abfrageoptimierungstools erzwungen.

Der OPTIMIZER_VERSION-Hinweis hat die höchste Priorität in Bezug auf die Version des Optimierungstools. Wenn der Anweisungshinweis angegeben ist, wird er unabhängig von allen anderen Versionseinstellungen für das Optimierungstool verwendet.

@{OPTIMIZER_VERSION=3} SELECT * FROM MyTable;

Sie können auch das Literal latest_version verwenden, um die Optimierungsversion für eine Abfrage auf die neueste Version festzulegen, wie hier gezeigt.

@{OPTIMIZER_VERSION=latest_version} SELECT * FROM MyTable;

Wenn der Hinweis OPTIMIZER_STATISTICS_PACKAGE für eine Anweisung festgelegt wird, wird diese Abfrage unter Verwendung der angegebenen Version des Statistikpakets der Abfrageoptimierung ausgeführt. Für das angegebene Paket muss die automatische Speicherbereinigung deaktiviert sein:

`ALTER STATISTICS <package_name> SET OPTIONS (allow_gc=false)`

Der Hinweis OPTIMIZER_STATISTICS_PACKAGE hat die höchste Priorität des Einstellungspaketpakets. Wenn der Anweisungshinweis angegeben wird, wird er unabhängig von allen anderen Versionseinstellungen des Optimierungstool-Pakets verwendet.

@{OPTIMIZER_STATISTICS_PACKAGE=auto_20191128_14_47_22UTC} SELECT * FROM MyTable;

Sie können auch das Literalformat latest verwenden, um das neueste Statistikpaket zu verwenden.

@{OPTIMIZER_STATISTICS_PACKAGE=latest} SELECT * FROM MyTable;

Beide Hinweise können wie im folgenden Beispiel in einer einzigen Anweisung festgelegt werden.

Mit dem Literal default_version wird die Optimierungsversion einer Abfrage auf die Standardversion festgelegt, die sich von der aktuellen Version unterscheiden kann. Weitere Informationen finden Sie unter Standardversion.

@{OPTIMIZER_VERSION=default_version, OPTIMIZER_STATISTICS_PACKAGE=auto_20191128_14_47_22UTC} SELECT * FROM myTable;

Optimierungsoptionen bei Verwendung des JDBC-Treibers festlegen

Sie können den Standardwert der Optimierungsversion und des Statistikpakets überschreiben, indem Sie Optionen im JDBC-Verbindungsstring angeben, wie im folgenden Beispiel gezeigt.

Diese Optionen werden nur in den neuesten Versionen des Open-Source-JDBC-Treibers unterstützt.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

class ConnectionWithQueryOptionsExample {

  static void connectionWithQueryOptions() throws SQLException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "my-project";
    String instanceId = "my-instance";
    String databaseId = "my-database";
    connectionWithQueryOptions(projectId, instanceId, databaseId);
  }

  static void connectionWithQueryOptions(String projectId, String instanceId, String databaseId)
      throws SQLException {
    String optimizerVersion = "1";
    String connectionUrl =
        String.format(
            "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s?optimizerVersion=%s",
            projectId, instanceId, databaseId, optimizerVersion);
    try (Connection connection = DriverManager.getConnection(connectionUrl);
        Statement statement = connection.createStatement()) {
      // Execute a query using the optimizer version '1'.
      try (ResultSet rs =
          statement.executeQuery(
              "SELECT SingerId, FirstName, LastName FROM Singers ORDER BY LastName")) {
        while (rs.next()) {
          System.out.printf("%d %s %s%n", rs.getLong(1), rs.getString(2), rs.getString(3));
        }
      }
      try (ResultSet rs = statement.executeQuery("SHOW VARIABLE OPTIMIZER_VERSION")) {
        while (rs.next()) {
          System.out.printf("Optimizer version: %s%n", rs.getString(1));
        }
      }
    }
  }
}

Sie können die Abfrageoptimierungsversion auch mit der Anweisung SET OPTIMIZER_VERSION festlegen, wie im folgenden Beispiel gezeigt.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

class SetQueryOptionsExample {

  static void setQueryOptions() throws SQLException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "my-project";
    String instanceId = "my-instance";
    String databaseId = "my-database";
    setQueryOptions(projectId, instanceId, databaseId);
  }

  static void setQueryOptions(String projectId, String instanceId, String databaseId)
      throws SQLException {
    String connectionUrl =
        String.format(
            "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s",
            projectId, instanceId, databaseId);
    try (Connection connection = DriverManager.getConnection(connectionUrl);
        Statement statement = connection.createStatement()) {
      // Instruct the JDBC connection to use version '1' of the query optimizer.
      statement.execute("SET OPTIMIZER_VERSION='1'");
      // Execute a query using the latest optimizer version.
      try (ResultSet rs =
          statement.executeQuery(
              "SELECT SingerId, FirstName, LastName FROM Singers ORDER BY LastName")) {
        while (rs.next()) {
          System.out.printf("%d %s %s%n", rs.getLong(1), rs.getString(2), rs.getString(3));
        }
      }
      try (ResultSet rs = statement.executeQuery("SHOW VARIABLE OPTIMIZER_VERSION")) {
        while (rs.next()) {
          System.out.printf("Optimizer version: %s%n", rs.getString(1));
        }
      }
    }
  }
}

Weitere Informationen zur Verwendung des Open-Source-Treibers finden Sie unter Open-Source-JDBC-Treiber verwenden.

Umgang mit ungültigen Optimierungstoolversionen

Cloud Spanner unterstützt mehrere Versionen des Optimierungstools. Welche Versionen unterstützt werden, ändert sich von Zeit zu Zeit, wenn das Abfrageoptimierungstool aktualisiert wird. Wenn die angegebene Version außerhalb des Bereichs liegt, schlägt Cloud Spanner die Abfrage fehl. Wenn Sie beispielsweise versuchen, eine Abfrage mit der Optimierungstool-Version = 100 auszuführen und dabei den aktuellen Maximalwert zu überschreiten, erhalten Sie den folgenden Fehler.

Ungültige Einstellung für ein Optimierungstool-Statistikpaket verarbeiten

Mit einer der weiter oben auf dieser Seite beschriebenen Methoden können Sie eine Datenbank oder eine Abfrage an ein beliebiges verfügbares Statistikpaket anpinnen. Eine Abfrage schlägt fehl, wenn ein ungültiger Statistikpaketname angegeben wird. Ein durch eine Abfrage angegebenes Statistikpaket muss entweder

Version des Optimierungstools für Abfragen festlegen, die zum Ausführen einer Abfrage verwendet wird

Die für eine Abfrage verwendete Version des Optimierungstools ist in gcloud spanner und über die Cloud Console sichtbar.

gcloud spanner

Wenn Sie die Version aufrufen möchten, die beim Ausführen einer Abfrage in gcloud spanner verwendet wird, setzen Sie das Flag --query-mode wie im folgenden Snippet gezeigt auf PROFILE.

gcloud spanner databases execute-sql MyDatabase --instance=test-instance \
    --query-mode=PROFILE --sql='SELECT * FROM MyTable'

Cloud Console

Führen Sie die Abfrage in der Ansicht Abfragedatenbank der Cloud Console aus und wählen Sie dann den Tab Erklärung aus, um die für eine Abfrage verwendete Version des Optimierungstools aufzurufen. Es wird eine Meldung ähnlich der folgenden angezeigt:

Diese Abfrage wurde mit der Optimierungsversion 3 ausgeführt.

Version der Abfrageoptimierung im Metrics Explorer visualisieren

Cloud Monitoring erfasst Messwerte, um die Leistung Ihrer Anwendungen und Systemdienste besser zu verstehen. Einer der für Cloud Spanner erfassten Messwerte ist die Anzahl der Abfragen. Damit wird die Anzahl der Abfragen in einer Instanz gemessen, die im Laufe der Zeit erfasst wurden. Dieser Messwert ist zwar sehr hilfreich, um Abfragen aufzurufen, die nach Fehlercode gruppiert sind, wir können ihn aber auch verwenden, um zu sehen, welche Version des Optimierungstools zur Ausführung der einzelnen Abfragen verwendet wurde.

Mit dem Metrics Explorer in der Cloud Console können Sie die Anzahl der Abfragen für Ihre Datenbankinstanz visualisieren. Abbildung 1 zeigt die Anzahl der Abfragen für drei Datenbanken. Sie sehen, welche Version des Optimierungstools in den einzelnen Datenbanken verwendet wird.

Die Tabelle unter dem Diagramm in dieser Abbildung zeigt, dass my-db-1 versucht hat, eine Abfrage mit einer ungültigen Optimierungstoolversion auszuführen, was den Status Falsche Nutzung zurückgibt und zu einer Abfrageanzahl von 0 führt. Die anderen Datenbanken haben Abfragen mit den Versionen 1 und 2 des Optimierungstools ausgeführt.

Grafik: Anzahl der Abfragen im Metrics Explorer nach der Version der Abfrageoptimierung

Abbildung 1. Anzahl der Abfragen, die im Metrics Explorer zusammen mit Abfragen angezeigt werden, die nach der Optimierungsversion gruppiert sind.

So richten Sie ein ähnliches Diagramm für Ihre Instanz ein:

  1. Rufen Sie in der Cloud Console den Metrics Explorer auf.
  2. Wählen Sie im Feld Ressourcentyp Cloud Spanner Instance aus.
  3. Wählen Sie im Feld Messwert die Option Count of queries aus.
  4. Wählen Sie im Feld Gruppieren nach die Optionen database, optimizer_version und status aus.

In diesem Beispiel wird nicht der Fall gezeigt, bei dem für verschiedene Abfragen in derselben Datenbank eine andere Optimierungstoolversion verwendet wird. In diesem Fall würde das Diagramm ein Balkendiagramm für jede Kombination aus Datenbank- und Optimierungstoolversion zeigen.

Informationen zum Monitoring Ihrer Cloud Spanner-Instanzen mit Cloud Monitoring finden Sie unter Monitoring mit Cloud Monitoring.