Gestire lo strumento di ottimizzazione delle query

Lo strumento di ottimizzazione delle query di Spanner determina il modo più efficiente per una query SQL. Tuttavia, il piano di query determinato dall'ottimizzatore cambiare leggermente quando si evolve lo stesso ottimizzatore delle query o quando il database le statistiche vengono aggiornate. Per ridurre al minimo qualsiasi potenziale di regressione delle prestazioni, Quando l'ottimizzatore delle query o le statistiche cambiano, Spanner fornisce le seguenti opzioni di query.

  • optimizer_version. Le modifiche apportate allo strumento di ottimizzazione delle query vengono raggruppate e rilasciate come versioni dell'ottimizzatore. Spanner inizia a utilizzare la versione più recente dell'ottimizzatore come predefinito almeno 30 giorni dopo il rilascio della versione. Puoi utilizzare l'opzione della versione dello strumento di ottimizzazione delle query per eseguire query su una versione precedente completamente gestita dall'ottimizzatore.

  • optimizer_statistics_package: Spanner aggiorna lo strumento di ottimizzazione statistiche regolarmente. Le nuove statistiche vengono rese disponibili sotto forma di pacchetto. Questa opzione di query specifica un pacchetto di statistiche che l'ottimizzatore delle query deve utilizzare durante la compilazione di una query SQL. Il pacchetto specificato deve contenere la garbage collection disattivata:

GoogleSQL

 ALTER STATISTICS  SET OPTIONS (allow_gc=false)

PostgreSQL

ALTER STATISTICS spanner."" SET OPTIONS (allow_gc = true)

Questa guida mostra come impostare queste singole opzioni su ambiti diversi in Spanner.

Elenca opzioni di ottimizzazione delle query

Spanner archivia le informazioni sulle versioni e sugli strumenti di ottimizzazione disponibili pacchetti di statistiche selezionabili.

Versioni ottimizzatore

La versione dello strumento di ottimizzazione delle query è un valore intero, incrementato di 1 a ogni aggiornamento. L'ultima versione dello strumento di ottimizzazione delle query è 7

Esegui questa istruzione SQL per restituire un elenco di tutti gli ottimizzatori supportati versioni, insieme alle date di uscita corrispondenti e se tali versioni è l'impostazione predefinita. Il numero di versione più grande restituito è quello supportato più di recente completamente gestita dall'ottimizzatore.

SELECT * FROM SPANNER_SYS.SUPPORTED_OPTIMIZER_VERSIONS;

Versione predefinita

Per impostazione predefinita, Spanner inizia a utilizzare la versione più recente dell'ottimizzatore in almeno 30 giorni dopo il rilascio della versione. Durante il periodo di oltre 30 giorni tra una nuova release e che diventerà quella predefinita, ti consigliamo di testare le query sulla nuova versione per rilevare eventuali regressioni.

Per trovare la versione predefinita, esegui questa istruzione SQL:

SELECT * FROM SPANNER_SYS.SUPPORTED_OPTIMIZER_VERSIONS;

La query restituisce un elenco di tutte le versioni degli ottimizzatori supportate. La La colonna IS_DEFAULT specifica la versione predefinita corrente.

Per maggiori dettagli su ciascuna versione, consulta Cronologia delle versioni dello strumento di ottimizzazione delle query.

Pacchetti di statistiche dell'ottimizzatore

Ogni nuovo pacchetto di statistiche di ottimizzazione creato da Spanner un nome di pacchetto con la garanzia di essere univoci all'interno per configurare un database.

Il formato del nome del pacchetto è auto_{PACKAGE_TIMESTAMP}UTC. In GoogleSQL, la classe ANALYZE attiva la creazione del nome del pacchetto di statistiche. Nella PostgreSQL, ANALYZE questa istruzione. Il formato del nome del pacchetto delle statistiche è analyze_{PACKAGE_TIMESTAMP}UTC, dove {PACKAGE_TIMESTAMP} è il timestamp, nel fuso orario UTC, di quando creazione delle statistiche avviata. Esegui questa istruzione SQL per restituire un di tutti i pacchetti di statistiche di ottimizzazione disponibili.

SELECT * FROM INFORMATION_SCHEMA.SPANNER_STATISTICS;

Per impostazione predefinita, Spanner utilizza il pacchetto di statistiche di ottimizzazione più recente a meno che il database o la query non vengano bloccati su un pacchetto più vecchio utilizzando uno dei descritti in questa pagina.

Priorità override opzione

Se usi un database di dialetti GoogleSQL, Spanner offre diversi modi per modificare le opzioni di ottimizzazione. Ad esempio, puoi impostare le opzioni per un una query specifica o configurare l'opzione nella libreria client durante il processo a livello di query. Quando un'opzione è impostata in più modi, viene applicata la seguente precedenza si applica l'ordine di acquisto. (Seleziona un link per passare alla sezione corrispondente di questo documento).

Valore predefinito Spanner ← opzione databaseapp clientvariabile di ambientequery clientSuggerimento istruzione

Ad esempio, ecco come interpretare l'ordine di precedenza quando imposti il parametro versione dello strumento di ottimizzazione delle query:

Quando crei un database, questo utilizza lo strumento Spanner versione predefinita dello strumento di ottimizzazione. L'impostazione della versione dello strumento di ottimizzazione utilizzando uno dei metodi sopra elencati richiede su qualsiasi elemento alla sua sinistra. Ad esempio, impostando lo strumento di ottimizzazione per un'app che utilizza una variabile di ambiente precedenza su qualsiasi valore impostato per il database utilizzando l'opzione di database. L'impostazione della versione dello strumento di ottimizzazione tramite un hint istruzione ha la precedenza più alta per la query specificata, che ha la precedenza sul set di valori utilizzando un altro metodo.

Esaminiamo ciascun metodo in maggiore dettaglio.

Imposta le opzioni di ottimizzazione a livello di database

Puoi impostare la versione predefinita dell'ottimizzatore su un database utilizzando quanto segue: ALTER DATABASE Comando DDL.

GoogleSQL

ALTER DATABASE MyDatabase
SET OPTIONS (optimizer_version =  7);

PostgreSQL

ALTER DATABASE MyDatabase SET spanner.optimizer_version = 5;

Puoi impostare il pacchetto di statistiche in modo simile, come illustrato di seguito esempio.

GoogleSQL

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

PostgreSQL

ALTER DATABASE MyDatabase
SET spanner.optimizer_statistics_package = "auto_20191128_14_47_22UTC";

Puoi anche impostare più opzioni contemporaneamente, come mostrato in successivo al comando DDL.

GoogleSQL

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

Puoi eseguire ALTER DATABASE in gcloud CLI con gcloud CLI databases ddl update come segue.

GoogleSQL

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

PostgreSQL

gcloud spanner databases ddl update MyDatabase --instance=test-instance \
  --ddl='ALTER DATABASE MyDatabase SET spanner.optimizer_version = 7'

Impostando un'opzione di database su NULL (in GoogleSQL) o DEFAULT (in PostgreSQL) lo cancella in modo che venga utilizzato il valore predefinito.

Per vedere il valore corrente di queste opzioni per un database, esegui una query INFORMATION_SCHEMA.DATABASE_OPTIONS per GoogleSQL, oppure information_schema database_options per PostgreSQL, come segue.

GoogleSQL

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')

PostgreSQL

  SELECT
    s.option_name,
    s.option_value
  FROM
    information_schema.database_options s
  WHERE
    s.schema_name='public'
    AND s.option_name IN ('optimizer_version',
      'optimizer_statistics_package')

Imposta le opzioni di ottimizzazione con le librerie client

Quando interagisci in modo programmatico con Spanner tramite client librerie, esistono vari modi per modificare le opzioni delle query un'applicazione client.

Per impostare lo strumento di ottimizzazione, devi utilizzare le versioni più recenti delle librerie client le opzioni di CPU e memoria disponibili.

Imposta le opzioni di ottimizzazione per un client di database

Un'applicazione può impostare le opzioni di ottimizzazione a livello globale nella libreria client configurando la proprietà delle opzioni di query come mostrato negli snippet di codice seguenti. Le impostazioni dello strumento di ottimizzazione vengono memorizzate nel client all'istanza e vengono applicate a tutte le query eseguite durante la durata del modello di alto profilo. Anche se le opzioni si applicano a livello di database nel backend, quando le opzioni sono impostate a livello di client, si applicano a tutti i database connessi quel cliente.

C++

namespace spanner = ::google::cloud::spanner;
spanner::Client client(
    spanner::MakeConnection(db),
    google::cloud::Options{}
        .set<spanner::QueryOptimizerVersionOption>("1")
        .set<spanner::QueryOptimizerStatisticsPackageOption>(
            "auto_20191128_14_47_22UTC"));

C#


using Google.Cloud.Spanner.Data;
using System.Collections.Generic;
using System.Threading.Tasks;

public class CreateConnectionWithQueryOptionsAsyncSample
{
    public class Album
    {
        public int AlbumId { get; set; }
        public int SingerId { get; set; }
        public string AlbumTitle { get; set; }
    }

    public async Task<List<Album>> CreateConnectionWithQueryOptionsAsync(string projectId, string instanceId, string databaseId)
    {
        string connectionString = $"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}";

        using var connection = new SpannerConnection(connectionString)
        {
            // Set query options on the connection.
            QueryOptions = QueryOptions.Empty
                .WithOptimizerVersion("1")
                // The list of available statistics packages for the database can
                // be found by querying the "INFORMATION_SCHEMA.SPANNER_STATISTICS"
                // table.
                .WithOptimizerStatisticsPackage("latest")
        };

        var albums = new List<Album>();
        var cmd = connection.CreateSelectCommand("SELECT SingerId, AlbumId, AlbumTitle FROM Albums");
        using var reader = await cmd.ExecuteReaderAsync();
        while (await reader.ReadAsync())
        {
            albums.Add(new Album
            {
                SingerId = reader.GetFieldValue<int>("SingerId"),
                AlbumId = reader.GetFieldValue<int>("AlbumId"),
                AlbumTitle = reader.GetFieldValue<string>("AlbumTitle")
            });
        }
        return albums;
    }
}

Vai


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(string $instanceId, string $databaseId): void
{
    $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": "latest",
    }
)
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("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

Imposta le opzioni di ottimizzazione con le variabili di ambiente

Per semplificare la prova di diverse impostazioni di ottimizzazione senza dover ricompilare la tua app, puoi impostare SPANNER_OPTIMIZER_VERSION e SPANNER_OPTIMIZER_STATISTICS_PACKAGE variabili di ambiente ed eseguire l'app, come mostrato nel seguente snippet.

Linux / MacOS

export SPANNER_OPTIMIZER_VERSION="7"
export SPANNER_OPTIMIZER_STATISTICS_PACKAGE="auto_20191128_14_47_22UTC"

Windows

set SPANNER_OPTIMIZER_VERSION="7"
  set SPANNER_OPTIMIZER_STATISTICS_PACKAGE="auto_20191128_14_47_22UTC"

I valori specificati per le opzioni di ottimizzazione delle query vengono letti e archiviati nel client al momento dell'inizializzazione del client e si applicano a tutte le query eseguite per tutta la durata del cliente.

Imposta le opzioni di ottimizzazione per una query del client

Puoi specificare un valore per la versione dell'ottimizzatore o per la versione del pacchetto di statistiche in il livello della query nell'applicazione client specificando le opzioni quando crei la query.

C++

void QueryWithQueryOptions(google::cloud::spanner::Client client) {
  namespace spanner = ::google::cloud::spanner;
  auto sql = spanner::SqlStatement("SELECT SingerId, FirstName FROM Singers");
  auto opts =
      google::cloud::Options{}
          .set<spanner::QueryOptimizerVersionOption>("1")
          .set<spanner::QueryOptimizerStatisticsPackageOption>("latest");
  auto rows = client.ExecuteQuery(std::move(sql), std::move(opts));

  using RowType = std::tuple<std::int64_t, std::string>;
  for (auto& row : spanner::StreamOf<RowType>(rows)) {
    if (!row) throw std::move(row).status();
    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#


using Google.Cloud.Spanner.Data;
using System.Collections.Generic;
using System.Threading.Tasks;

public class RunCommandWithQueryOptionsAsyncSample
{
    public class Album
    {
        public int SingerId { get; set; }
        public int AlbumId { get; set; }
        public string AlbumTitle { get; set; }
    }

    public async Task<List<Album>> RunCommandWithQueryOptionsAsync(string projectId, string instanceId, string databaseId)
    {
        var connectionString = $"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}";
        using var connection = new SpannerConnection(connectionString);
        using var cmd = connection.CreateSelectCommand("SELECT SingerId, AlbumId, AlbumTitle FROM Albums");

        cmd.QueryOptions = QueryOptions.Empty
            .WithOptimizerVersion("1")
            // The list of available statistics packages for the database can
            // be found by querying the "INFORMATION_SCHEMA.SPANNER_STATISTICS"
            // table.
            .WithOptimizerStatisticsPackage("latest");
        var albums = new List<Album>();
        using var reader = await cmd.ExecuteReaderAsync();
        while (await reader.ReadAsync())
        {
            albums.Add(new Album()
            {
                AlbumId = reader.GetFieldValue<int>("AlbumId"),
                SingerId = reader.GetFieldValue<int>("SingerId"),
                AlbumTitle = reader.GetFieldValue<string>("AlbumTitle")
            });
        }
        return albums;
    }
}

Vai


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(string $instanceId, string $databaseId): void
{
    $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("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

Impostare le opzioni di ottimizzazione per una query utilizzando un suggerimento di istruzioni

Un suggerimento istruzione è un hint su un'istruzione di query che modifica l'esecuzione della query dal comportamento predefinito. Impostazione del suggerimento OPTIMIZER_VERSION attivato un'istruzione ne forza l'esecuzione utilizzando lo strumento di ottimizzazione delle query specificato completamente gestita.

Il hint OPTIMIZER_VERSION ha la precedenza più alta in termini di versione dell'ottimizzatore. Se il hint dell'istruzione è specificato, verrà usato indipendentemente da tutte le altre le impostazioni della versione dello strumento di ottimizzazione.

GoogleSQL

@{OPTIMIZER_VERSION=7} SELECT * FROM MyTable;

PostgreSQL

/*@OPTIMIZER_VERSION=7*/ SELECT * FROM MyTable;

Puoi anche utilizzare il valore letterale latest_version per impostare la versione dello strumento di ottimizzazione eseguire una query all'ultima versione, come mostrato qui.

GoogleSQL

@{OPTIMIZER_VERSION=latest_version} SELECT * FROM MyTable;

PostgreSQL

/*@OPTIMIZER_VERSION=latest_version*/ SELECT * FROM MyTable;

Impostazione del suggerimento OPTIMIZER_STATISTICS_PACKAGE attivato un'istruzione ne forza l'esecuzione utilizzando lo strumento di ottimizzazione delle query specificato del pacchetto di statistiche. Il pacchetto specificato è necessario che la garbage collection sia disattivata:

GoogleSQL

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

PostgreSQL

ALTER STATISTICS spanner."package_name" SET OPTIONS (allow_gc=false)

Il suggerimento OPTIMIZER_STATISTICS_PACKAGE ha il pacchetto di ottimizzazione più alto l'impostazione della precedenza. Se il hint dell'istruzione è specificato, verrà usato a prescindere da tutte le altre impostazioni della versione del pacchetto di ottimizzazione.

@{OPTIMIZER_STATISTICS_PACKAGE=auto_20191128_14_47_22UTC} SELECT * FROM MyTable;

Per utilizzare il pacchetto di statistiche più recente, puoi anche utilizzare il valore letterale latest.

@{OPTIMIZER_STATISTICS_PACKAGE=latest} SELECT * FROM MyTable;

Entrambi i suggerimenti possono essere impostati in una singola istruzione, come mostrato nell'esempio seguente.

Il valore letterale default_version imposta la versione dello strumento di ottimizzazione per una query sul predefinita, che potrebbe essere diversa dall'ultima versione. Consulta Versione predefinita per i dettagli.

GoogleSQL

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

PostgreSQL

/*@OPTIMIZER_VERSION=default_version, OPTIMIZER_STATISTICS_PACKAGE=auto_20191128_14_47_22UTC*/ SELECT * FROM KeyValue;

Impostare le opzioni di ottimizzazione quando si utilizza il driver JDBC di Spanner

Puoi sostituire il valore predefinito della versione e delle statistiche dello strumento di ottimizzazione specificando le opzioni nella stringa di connessione JDBC, come mostrato dall'esempio seguente.

Queste opzioni sono supportate solo nelle versioni più recenti del Driver JDBC di Spanner.

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

Puoi anche impostare la versione dello strumento di ottimizzazione delle query utilizzando SET OPTIMIZER_VERSION come mostrato nell'esempio seguente.

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.
      // NOTE: Use `SET SPANNER.OPTIMIZER_VERSION='1`` when connected to a PostgreSQL database.
      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));
        }
      }
      // NOTE: Use `SHOW SPANNER.OPTIMIZER_VERSION` when connected to a PostgreSQL database.
      try (ResultSet rs = statement.executeQuery("SHOW VARIABLE OPTIMIZER_VERSION")) {
        while (rs.next()) {
          System.out.printf("Optimizer version: %s%n", rs.getString(1));
        }
      }
    }
  }
}

Per maggiori dettagli sull'utilizzo del driver open source, vedi Utilizzo del driver JDBC open source.

Come vengono gestite le versioni dello strumento di ottimizzazione non valide

Spanner supporta una gamma di versioni dello strumento di ottimizzazione. Questo intervallo cambia nel tempo, quando lo strumento di ottimizzazione delle query viene aggiornato. Se la versione specificato è fuori intervallo, la query ha esito negativo. Ad esempio, se tenti di eseguire una query con l'istruzione hint @{OPTIMIZER_VERSION=8}, mentre il numero di versione più recente dell'ottimizzatore è 7, Spanner risponde con questo messaggio di errore:

Query optimizer version: 8 is not supported

Gestire un'impostazione del pacchetto di statistiche di ottimizzazione non valida

Puoi fissare il tuo database o eseguire una query pacchetto di statistiche disponibile utilizzando uno dei metodi descritti in precedenza in questa pagina. R non va a buon fine se viene fornito un nome di pacchetto di statistiche non valido. Statistiche A specificato da una query deve essere:

Determinare la versione dello strumento di ottimizzazione delle query utilizzata per eseguire una query

La versione dell'ottimizzatore utilizzata per una query è visibile tramite la console Google Cloud e in Google Cloud CLI.

Console Google Cloud

Per visualizzare la versione dello strumento di ottimizzazione utilizzata per una query, eseguila nel Spanner Studio della console Google Cloud e seleziona Scheda Spiegazione. Dovresti vedere un messaggio simile al seguente:

Versione dello strumento di ottimizzazione delle query: 7

Interfaccia a riga di comando gcloud

Per visualizzare la versione utilizzata durante l'esecuzione di una query in gcloud CLI, imposta il flag --query-mode a PROFILE, come mostrato nello snippet seguente.

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

Visualizza la versione dello strumento di ottimizzazione delle query in Metrics Explorer

Cloud Monitoring raccoglie misurazioni per aiutarti a comprendere in che modo le prestazioni delle applicazioni e dei servizi di sistema. Una delle metriche raccolte per Spanner è il conteggio di query, che misura il numero di query in un'istanza, campionate nel tempo. Sebbene questa metrica sia molto utile per visualizzare le query raggruppate per codice di errore, possiamo utilizzarlo anche per vedere quale ottimizzatore è stata utilizzata per eseguire ogni query.

Puoi utilizzare Esplora metriche in Console Google Cloud per visualizzare il Conteggio delle query per il tuo database in esecuzione in un'istanza Compute Engine. La figura 1 mostra il conteggio delle query per tre database. Puoi vedere quale versione dell'ottimizzatore viene utilizzata in ciascun database.

La tabella sotto il grafico in questa figura mostra che my-db-1 ha tentato di eseguire una query con una versione dello strumento di ottimizzazione non valida, che restituisce lo stato Utilizzo scadente generando un conteggio delle query pari a 0. Gli altri database hanno eseguito le query utilizzando la versione 1 e 2 dello strumento di ottimizzazione.

Conteggio delle query in Metrics Explorer raggruppate per versione dello strumento di ottimizzazione delle query

Figura 1. Numero di query visualizzate in Metrics Explorer con query raggruppate per versione dell'ottimizzatore.

Per configurare un grafico simile per la tua istanza:

  1. Vai a Metrics Explorer nella console Google Cloud.
  2. Nel campo Tipo di risorsa, seleziona Cloud Spanner Instance.
  3. Nel campo Metrica, seleziona Count of queries.
  4. Nel campo Raggruppa per, seleziona database, optimizer_version e status.

Non mostrato in questo esempio è il caso in cui una versione dello strumento di ottimizzazione diversa utilizzate per query diverse nello stesso database. In questo caso, il grafico mostra un segmento a barre per ogni combinazione di database e ottimizzatore completamente gestita.

Scopri come utilizzare Cloud Monitoring per monitorare Spanner consulta Monitoraggio con Cloud Monitoring