Mulai menggunakan Spanner di PHP


Tujuan

Tutorial ini memandu Anda melalui langkah-langkah berikut menggunakan library klien Spanner untuk PHP:

  • Membuat instance dan database Spanner.
  • Menulis, membaca, dan mengeksekusi kueri SQL pada data di database.
  • Perbarui skema database.
  • Perbarui data menggunakan transaksi baca-tulis.
  • Tambahkan indeks sekunder ke database.
  • Gunakan indeks untuk membaca dan menjalankan kueri SQL pada data.
  • Ambil data menggunakan transaksi hanya baca.

Biaya

Tutorial ini menggunakan Spanner, yang merupakan komponen Google Cloud yang dapat ditagih. Untuk mengetahui informasi tentang biaya penggunaan Spanner, lihat Harga.

Sebelum memulai

Selesaikan langkah-langkah yang dijelaskan di bagian Menyiapkan, yang mencakup pembuatan dan penetapan project Google Cloud default, pengaktifan penagihan, pengaktifan Cloud Spanner API, dan penyiapan OAuth 2.0 untuk mendapatkan kredensial autentikasi guna menggunakan Cloud Spanner API.

Secara khusus, pastikan Anda menjalankan gcloud auth application-default login untuk menyiapkan lingkungan pengembangan lokal dengan kredensial autentikasi.

Menyiapkan lingkungan PHP lokal

  1. Ikuti langkah-langkah di Akun layanan untuk menyiapkan akun layanan sebagai Kredensial Default Aplikasi Anda. Dengan mengikuti langkah-langkah tersebut, Anda akan mendapatkan file kunci akun layanan (dalam JSON) dan variabel lingkungan GOOGLE_APPLICATION_CREDENTIALS yang akan memungkinkan Anda melakukan autentikasi ke Spanner API.

  2. Instal hal berikut di mesin pengembangan Anda jika belum diinstal:

  3. Clone repositori aplikasi contoh ke komputer lokal Anda:

    git clone https://github.com/GoogleCloudPlatform/php-docs-samples
    

    Atau, Anda dapat mendownload sampel sebagai file ZIP dan mengekstraknya.

  4. Ubah ke direktori yang berisi kode contoh Spanner:

    cd php-docs-samples/spanner
    
  5. Instal dependensi:

    composer install
    

    Tindakan ini akan menginstal library klien Spanner untuk PHP, yang dapat Anda tambahkan ke project apa pun dengan menjalankan composer require google/cloud-spanner.

Membuat instance

Saat pertama kali menggunakan Spanner, Anda harus membuat instance, yang merupakan alokasi resource yang digunakan oleh database Spanner. Saat membuat instance, Anda memilih konfigurasi instance, yang menentukan tempat data Anda disimpan, dan juga jumlah node yang akan digunakan, yang menentukan jumlah resource penyimpanan dan penayangan di instance Anda.

Jalankan perintah berikut untuk membuat instance Spanner di region us-central1 dengan 1 node:

gcloud spanner instances create test-instance --config=regional-us-central1 \
    --description="Test Instance" --nodes=1

Perhatikan bahwa tindakan ini akan membuat instance dengan karakteristik berikut:

  • ID Instance test-instance
  • Nama tampilan Test Instance
  • Konfigurasi instance regional-us-central1 (Konfigurasi regional menyimpan data di satu region, sedangkan konfigurasi multi-region mendistribusikan data di beberapa region. Untuk mengetahui informasi selengkapnya, lihat Tentang instance.)
  • Jumlah node 1 (node_count sesuai dengan jumlah resource penyimpanan dan penayangan yang tersedia untuk database dalam instance. Pelajari lebih lanjut di Node dan unit pemrosesan.)

Anda akan melihat:

Creating instance...done.

Menelusuri file contoh

Repositori contoh berisi contoh yang menunjukkan cara menggunakan Spanner dengan PHP.

Lihat fungsi di src/create_database.php dan src/add_column.php, yang menunjukkan cara membuat database dan mengubah skema database. Data menggunakan contoh skema yang ditampilkan di halaman Skema dan model data.

Buat database

GoogleSQL

php src/create_database.php test-instance example-db

PostgreSQL

php src/pg_create_database.php test-instance example-db

Anda akan melihat:

Created database example-db on instance test-instance
Kode berikut membuat database dan dua tabel dalam database.

GoogleSQL

use Google\Cloud\Spanner\Admin\Database\V1\Client\DatabaseAdminClient;
use Google\Cloud\Spanner\Admin\Database\V1\CreateDatabaseRequest;

/**
 * Creates a database and tables for sample data.
 * Example:
 * ```
 * create_database($instanceId, $databaseId);
 * ```
 *
 * @param string $projectId The Google Cloud project ID.
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function create_database(string $projectId, string $instanceId, string $databaseId): void
{
    $databaseAdminClient = new DatabaseAdminClient();
    $instance = $databaseAdminClient->instanceName($projectId, $instanceId);

    $operation = $databaseAdminClient->createDatabase(
        new CreateDatabaseRequest([
            'parent' => $instance,
            'create_statement' => sprintf('CREATE DATABASE `%s`', $databaseId),
            'extra_statements' => [
                'CREATE TABLE Singers (' .
                'SingerId     INT64 NOT NULL,' .
                'FirstName    STRING(1024),' .
                'LastName     STRING(1024),' .
                'SingerInfo   BYTES(MAX),' .
                'FullName     STRING(2048) AS' .
                '(ARRAY_TO_STRING([FirstName, LastName], " ")) STORED' .
                ') PRIMARY KEY (SingerId)',
                'CREATE TABLE Albums (' .
                    'SingerId     INT64 NOT NULL,' .
                    'AlbumId      INT64 NOT NULL,' .
                    'AlbumTitle   STRING(MAX)' .
                ') PRIMARY KEY (SingerId, AlbumId),' .
                'INTERLEAVE IN PARENT Singers ON DELETE CASCADE'
            ]
        ])
    );

    print('Waiting for operation to complete...' . PHP_EOL);
    $operation->pollUntilComplete();

    printf('Created database %s on instance %s' . PHP_EOL,
        $databaseId, $instanceId);
}

PostgreSQL

use Google\Cloud\Spanner\Admin\Database\V1\Client\DatabaseAdminClient;
use Google\Cloud\Spanner\Admin\Database\V1\CreateDatabaseRequest;
use Google\Cloud\Spanner\Admin\Database\V1\DatabaseDialect;
use Google\Cloud\Spanner\Admin\Database\V1\GetDatabaseRequest;
use Google\Cloud\Spanner\Admin\Database\V1\UpdateDatabaseDdlRequest;

/**
 * Creates a database that uses Postgres dialect
 *
 * @param string $projectId The Google Cloud project ID.
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function pg_create_database(string $projectId, string $instanceId, string $databaseId): void
{
    $databaseAdminClient = new DatabaseAdminClient();
    $instance = $databaseAdminClient->instanceName($projectId, $instanceId);
    $databaseName = $databaseAdminClient->databaseName($projectId, $instanceId, $databaseId);

    $table1Query = 'CREATE TABLE Singers (
        SingerId   bigint NOT NULL PRIMARY KEY,
        FirstName  varchar(1024),
        LastName   varchar(1024),
        SingerInfo bytea,
        FullName character varying(2048) GENERATED
        ALWAYS AS (FirstName || \' \' || LastName) STORED
    )';
    $table2Query = 'CREATE TABLE Albums (
        AlbumId      bigint NOT NULL,
        SingerId     bigint NOT NULL REFERENCES Singers (SingerId),
        AlbumTitle   text,
        PRIMARY KEY(SingerId, AlbumId)
    )';

    $operation = $databaseAdminClient->createDatabase(
        new CreateDatabaseRequest([
            'parent' => $instance,
            'create_statement' => sprintf('CREATE DATABASE "%s"', $databaseId),
            'extra_statements' => [],
            'database_dialect' => DatabaseDialect::POSTGRESQL
        ])
    );

    print('Waiting for operation to complete...' . PHP_EOL);
    $operation->pollUntilComplete();

    $request = new UpdateDatabaseDdlRequest([
        'database' => $databaseName,
        'statements' => [$table1Query, $table2Query]
    ]);

    $operation = $databaseAdminClient->updateDatabaseDdl($request);
    $operation->pollUntilComplete();

    $database = $databaseAdminClient->getDatabase(
        new GetDatabaseRequest(['name' => $databaseAdminClient->databaseName($projectId, $instanceId, $databaseId)])
    );
    $dialect = DatabaseDialect::name($database->getDatabaseDialect());

    printf('Created database %s with dialect %s on instance %s' . PHP_EOL,
        $databaseId, $dialect, $instanceId);
}

Langkah berikutnya adalah menulis data ke database Anda.

Membuat klien database

Untuk melakukan operasi baca dan tulis, Anda perlu mendapatkan instance Google\Cloud\Spanner\Database.

# Includes the autoloader for libraries installed with composer
require __DIR__ . '/vendor/autoload.php';

# Imports the Google Cloud client library
use Google\Cloud\Spanner\SpannerClient;

# Your Google Cloud Platform project ID
$projectId = 'YOUR_PROJECT_ID';

# Instantiates a client
$spanner = new SpannerClient([
    'projectId' => $projectId
]);

# Your Cloud Spanner instance ID.
$instanceId = 'your-instance-id';

# Get a Cloud Spanner instance by ID.
$instance = $spanner->instance($instanceId);

# Your Cloud Spanner database ID.
$databaseId = 'your-database-id';

# Get a Cloud Spanner database by ID.
$database = $instance->database($databaseId);

# Execute a simple SQL statement.
$results = $database->execute('SELECT "Hello World" as test');

foreach ($results as $row) {
    print($row['test'] . PHP_EOL);
}

Anda dapat menganggap Database sebagai koneksi database: semua interaksi Anda dengan Spanner harus melalui Database. Biasanya, Anda membuat Database saat aplikasi dimulai, lalu Anda menggunakan kembali Database tersebut untuk membaca, menulis, dan menjalankan transaksi. Setiap klien menggunakan resource di Spanner.

Jika membuat beberapa klien di aplikasi yang sama, Anda harus memanggil Database::close untuk membersihkan resource klien, termasuk koneksi jaringan, segera setelah tidak diperlukan lagi.

Baca selengkapnya di referensi Database.

Menulis data dengan DML

Anda dapat menyisipkan data menggunakan Bahasa Manipulasi Data (DML) dalam transaksi baca-tulis.

Anda menggunakan metode executeUpdate() untuk mengeksekusi pernyataan DML.

use Google\Cloud\Spanner\SpannerClient;
use Google\Cloud\Spanner\Transaction;

/**
 * Inserts sample data into the given database with a DML statement.
 *
 * The database and table must already exist and can be created using
 * `create_database`.
 * Example:
 * ```
 * insert_data($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function write_data_with_dml(string $instanceId, string $databaseId): void
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);
    $database = $instance->database($databaseId);

    $database->runTransaction(function (Transaction $t) {
        $rowCount = $t->executeUpdate(
            'INSERT Singers (SingerId, FirstName, LastName) VALUES '
            . "(12, 'Melissa', 'Garcia'), "
            . "(13, 'Russell', 'Morales'), "
            . "(14, 'Jacqueline', 'Long'), "
            . "(15, 'Dylan', 'Shaw')");
        $t->commit();
        printf('Inserted %d row(s).' . PHP_EOL, $rowCount);
    });
}

Jalankan file contoh src/write_data_with_dml.php.

php src/write_data_with_dml.php test-instance example-db

Anda akan melihat:

Inserted 4 row(s).

Menulis data dengan mutasi

Anda juga dapat menyisipkan data menggunakan mutasi.

Anda menulis data menggunakan metode Database::insertBatch. insertBatch menambahkan baris baru ke tabel. Semua penyisipan dalam satu batch diterapkan secara atomik.

Kode ini menunjukkan cara menulis data menggunakan mutasi:

use Google\Cloud\Spanner\SpannerClient;

/**
 * Inserts sample data into the given database.
 *
 * The database and table must already exist and can be created using
 * `create_database`.
 * Example:
 * ```
 * insert_data($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function insert_data(string $instanceId, string $databaseId): void
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);
    $database = $instance->database($databaseId);

    $operation = $database->transaction(['singleUse' => true])
        ->insertBatch('Singers', [
            ['SingerId' => 1, 'FirstName' => 'Marc', 'LastName' => 'Richards'],
            ['SingerId' => 2, 'FirstName' => 'Catalina', 'LastName' => 'Smith'],
            ['SingerId' => 3, 'FirstName' => 'Alice', 'LastName' => 'Trentor'],
            ['SingerId' => 4, 'FirstName' => 'Lea', 'LastName' => 'Martin'],
            ['SingerId' => 5, 'FirstName' => 'David', 'LastName' => 'Lomond'],
        ])
        ->insertBatch('Albums', [
            ['SingerId' => 1, 'AlbumId' => 1, 'AlbumTitle' => 'Total Junk'],
            ['SingerId' => 1, 'AlbumId' => 2, 'AlbumTitle' => 'Go, Go, Go'],
            ['SingerId' => 2, 'AlbumId' => 1, 'AlbumTitle' => 'Green'],
            ['SingerId' => 2, 'AlbumId' => 2, 'AlbumTitle' => 'Forever Hold Your Peace'],
            ['SingerId' => 2, 'AlbumId' => 3, 'AlbumTitle' => 'Terrified']
        ])
        ->commit();

    print('Inserted data.' . PHP_EOL);
}

Jalankan file contoh src/insert_data.php.

php src/insert_data.php test-instance example-db

Anda akan melihat:

Inserted data.

Membuat kueri data menggunakan SQL

Spanner mendukung antarmuka SQL untuk membaca data, yang dapat Anda akses di command line menggunakan Google Cloud CLI atau secara terprogram menggunakan library klien Spanner untuk PHP.

Di command line

Jalankan pernyataan SQL berikut untuk membaca nilai semua kolom dari tabel Albums:

gcloud spanner databases execute-sql example-db --instance=test-instance \
    --sql='SELECT SingerId, AlbumId, AlbumTitle FROM Albums'

Hasilnya akan menjadi:

SingerId AlbumId AlbumTitle
1        1       Total Junk
1        2       Go, Go, Go
2        1       Green
2        2       Forever Hold Your Peace
2        3       Terrified

Menggunakan library klien Spanner untuk PHP

Selain menjalankan pernyataan SQL di command line, Anda dapat mengeluarkan pernyataan SQL yang sama secara terprogram menggunakan library klien Spanner untuk PHP.

Gunakan Database::execute() untuk menjalankan kueri SQL.

Berikut cara mengeluarkan kueri dan mengakses data:

use Google\Cloud\Spanner\SpannerClient;

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

    $results = $database->execute(
        'SELECT SingerId, AlbumId, AlbumTitle FROM Albums'
    );

    foreach ($results as $row) {
        printf('SingerId: %s, AlbumId: %s, AlbumTitle: %s' . PHP_EOL,
            $row['SingerId'], $row['AlbumId'], $row['AlbumTitle']);
    }
}

Jalankan file contoh src/query_data.php.

php src/query_data.php test-instance example-db

Anda akan melihat hasil berikut:

SingerId: 2, AlbumId: 2, AlbumTitle: Forever Hold Your Peace
SingerId: 1, AlbumId: 2, AlbumTitle: Go, Go, Go
SingerId: 2, AlbumId: 1, AlbumTitle: Green
SingerId: 2, AlbumId: 3, AlbumTitle: Terrified
SingerId: 1, AlbumId: 1, AlbumTitle: Total Junk

Hasil Anda tidak harus dalam urutan ini. Jika Anda perlu memastikan urutan hasilnya, gunakan klausa ORDER BY, seperti yang didokumentasikan dalam praktik terbaik SQL.

Membuat kueri menggunakan parameter SQL

Jika aplikasi Anda memiliki kueri yang sering dieksekusi, Anda dapat meningkatkan performanya dengan memparametrisasi kueri tersebut. Kueri berparameter yang dihasilkan dapat di-cache dan digunakan kembali, yang mengurangi biaya kompilasi. Untuk informasi selengkapnya, lihat Menggunakan parameter kueri untuk mempercepat kueri yang sering dieksekusi.

Berikut adalah contoh penggunaan parameter dalam klausa WHERE untuk mengkueri kumpulan data yang berisi nilai tertentu untuk LastName.

use Google\Cloud\Spanner\SpannerClient;

/**
 * Queries sample data from the database using SQL with a parameter.
 * Example:
 * ```
 * query_data_with_parameter($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function query_data_with_parameter(string $instanceId, string $databaseId): void
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);
    $database = $instance->database($databaseId);

    $results = $database->execute(
        'SELECT SingerId, FirstName, LastName FROM Singers ' .
        'WHERE LastName = @lastName',
        ['parameters' => ['lastName' => 'Garcia']]
    );

    foreach ($results as $row) {
        printf('SingerId: %s, FirstName: %s, LastName: %s' . PHP_EOL,
            $row['SingerId'], $row['FirstName'], $row['LastName']);
    }
}

Jalankan file contoh src/query_data_with_parameter.php.

php src/query_data_with_parameter.php test-instance example-db

Anda akan melihat hasil berikut:

SingerId: 12, FirstName: Melissa, LastName: Garcia

Membaca data menggunakan read API

Selain antarmuka SQL Spanner, Spanner juga mendukung antarmuka baca.

Gunakan Database::read() untuk membaca baris dari database. Gunakan objek KeySet untuk menentukan kumpulan kunci dan rentang kunci yang akan dibaca.

Berikut cara membaca data:

use Google\Cloud\Spanner\SpannerClient;

/**
 * Reads sample data from the database.
 * Example:
 * ```
 * read_data($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function read_data(string $instanceId, string $databaseId): void
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);
    $database = $instance->database($databaseId);

    $keySet = $spanner->keySet(['all' => true]);
    $results = $database->read(
        'Albums',
        $keySet,
        ['SingerId', 'AlbumId', 'AlbumTitle']
    );

    foreach ($results->rows() as $row) {
        printf('SingerId: %s, AlbumId: %s, AlbumTitle: %s' . PHP_EOL,
            $row['SingerId'], $row['AlbumId'], $row['AlbumTitle']);
    }
}

Jalankan contoh dalam file read_data.php.

php read_data.php test-instance example-db

Anda akan melihat output yang mirip dengan:

SingerId: 1, AlbumId: 1, AlbumTitle: Total Junk
SingerId: 1, AlbumId: 2, AlbumTitle: Go, Go, Go
SingerId: 2, AlbumId: 1, AlbumTitle: Green
SingerId: 2, AlbumId: 2, AlbumTitle: Forever Hold your Peace
SingerId: 2, AlbumId: 3, AlbumTitle: Terrified

Memperbarui skema database

Anggaplah Anda perlu menambahkan kolom baru bernama MarketingBudget ke tabel Albums. Menambahkan kolom baru ke tabel yang ada memerlukan pembaruan pada skema database Anda. Spanner mendukung pembaruan skema ke database saat database terus menyalurkan traffic. Pembaruan skema tidak memerlukan database offline dan tidak mengunci seluruh tabel atau kolom; Anda dapat terus menulis data ke database selama pembaruan skema. Baca selengkapnya tentang pembaruan skema yang didukung dan performa perubahan skema di Melakukan pembaruan skema.

Menambahkan kolom

Anda dapat menambahkan kolom di command line menggunakan Google Cloud CLI atau secara terprogram menggunakan library klien Spanner untuk PHP.

Di command line

Gunakan perintah ALTER TABLE berikut untuk menambahkan kolom baru ke tabel:

GoogleSQL

gcloud spanner databases ddl update example-db --instance=test-instance \
    --ddl='ALTER TABLE Albums ADD COLUMN MarketingBudget INT64'

PostgreSQL

gcloud spanner databases ddl update example-db --instance=test-instance \
    --ddl='ALTER TABLE Albums ADD COLUMN MarketingBudget BIGINT'

Anda akan melihat:

Schema updating...done.

Menggunakan library klien Spanner untuk PHP

Gunakan Database::updateDdl untuk mengubah skema:

use Google\Cloud\Spanner\Admin\Database\V1\Client\DatabaseAdminClient;
use Google\Cloud\Spanner\Admin\Database\V1\UpdateDatabaseDdlRequest;

/**
 * Adds a new column to the Albums table in the example database.
 * Example:
 * ```
 * add_column($projectId, $instanceId, $databaseId);
 * ```
 *
 * @param string $projectId The Google Cloud project ID.
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function add_column(string $projectId, string $instanceId, string $databaseId): void
{
    $databaseAdminClient = new DatabaseAdminClient();
    $databaseName = DatabaseAdminClient::databaseName($projectId, $instanceId, $databaseId);

    $request = new UpdateDatabaseDdlRequest([
        'database' => $databaseName,
        'statements' => ['ALTER TABLE Albums ADD COLUMN MarketingBudget INT64']
    ]);

    $operation = $databaseAdminClient->updateDatabaseDdl($request);

    print('Waiting for operation to complete...' . PHP_EOL);
    $operation->pollUntilComplete();

    printf('Added the MarketingBudget column.' . PHP_EOL);
}

Jalankan file contoh src/add_column.php.

php src/add_column.php test-instance example-db

Anda akan melihat:

Added the MarketingBudget column.

Menulis data ke kolom baru

Kode berikut menulis data ke kolom baru. Fungsi ini menetapkan MarketingBudget ke 100000 untuk baris yang diberi kunci oleh Albums(1, 1) dan ke 500000 untuk baris yang diberi kunci oleh Albums(2, 2).

use Google\Cloud\Spanner\SpannerClient;

/**
 * Updates sample data in the database.
 *
 * This updates the `MarketingBudget` column which must be created before
 * running this sample. You can add the column by running the `add_column`
 * sample or by running this DDL statement against your database:
 *
 *     ALTER TABLE Albums ADD COLUMN MarketingBudget INT64
 *
 * Example:
 * ```
 * update_data($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function update_data(string $instanceId, string $databaseId): void
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);
    $database = $instance->database($databaseId);

    $operation = $database->transaction(['singleUse' => true])
        ->updateBatch('Albums', [
            ['SingerId' => 1, 'AlbumId' => 1, 'MarketingBudget' => 100000],
            ['SingerId' => 2, 'AlbumId' => 2, 'MarketingBudget' => 500000],
        ])
        ->commit();

    print('Updated data.' . PHP_EOL);
}

Jalankan file contoh src/update_data.php.

php src/update_data.php test-instance example-db

Anda akan melihat:

Updated data.

Anda juga dapat menjalankan kueri SQL atau panggilan baca untuk mengambil nilai yang baru saja Anda tulis.

Berikut adalah kode untuk menjalankan kueri:

use Google\Cloud\Spanner\SpannerClient;

/**
 * Queries sample data from the database using SQL.
 * This sample uses the `MarketingBudget` column. You can add the column
 * by running the `add_column` sample or by running this DDL statement against
 * your database:
 *
 *      ALTER TABLE Albums ADD COLUMN MarketingBudget INT64
 *
 * Example:
 * ```
 * query_data_with_new_column($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function query_data_with_new_column(string $instanceId, string $databaseId): void
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);
    $database = $instance->database($databaseId);

    $results = $database->execute(
        'SELECT SingerId, AlbumId, MarketingBudget FROM Albums'
    );

    foreach ($results as $row) {
        printf('SingerId: %s, AlbumId: %s, MarketingBudget: %d' . PHP_EOL,
            $row['SingerId'], $row['AlbumId'], $row['MarketingBudget']);
    }
}

Untuk menjalankan kueri ini, jalankan file contoh src/query-data-with-new-column.php.

php src/query_data_with_new_column.php test-instance example-db

Anda akan melihat:

SingerId: 1, AlbumId: 1, MarketingBudget: 100000
SingerId: 1, AlbumId: 2, MarketingBudget: 0
SingerId: 2, AlbumId: 1, MarketingBudget: 0
SingerId: 2, AlbumId: 2, MarketingBudget: 500000
SingerId: 2, AlbumId: 3, MarketingBudget: 0

Memperbarui data

Anda dapat memperbarui data menggunakan DML dalam transaksi baca-tulis.

Anda menggunakan metode executeUpdate() untuk mengeksekusi pernyataan DML.

use Google\Cloud\Spanner\SpannerClient;
use Google\Cloud\Spanner\Transaction;

/**
 * Performs a read-write transaction to update two sample records in the
 * database.
 *
 * This will transfer 200,000 from the `MarketingBudget` field for the second
 * Album to the first Album. If the `MarketingBudget` for the second Album is
 * too low, it will raise an exception.
 *
 * Before running this sample, you will need to run the `update_data` sample
 * to populate the fields.
 * Example:
 * ```
 * write_data_with_dml_transaction($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function write_data_with_dml_transaction(string $instanceId, string $databaseId): void
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);
    $database = $instance->database($databaseId);

    $database->runTransaction(function (Transaction $t) {
        // Transfer marketing budget from one album to another. We do it in a transaction to
        // ensure that the transfer is atomic.
        $transferAmount = 200000;

        $results = $t->execute(
            'SELECT MarketingBudget from Albums WHERE SingerId = 2 and AlbumId = 2'
        );
        $resultsRow = $results->rows()->current();
        $album2budget = $resultsRow['MarketingBudget'];

        // Transaction will only be committed if this condition still holds at the time of
        // commit. Otherwise it will be aborted and the callable will be rerun by the
        // client library.
        if ($album2budget >= $transferAmount) {
            $results = $t->execute(
                'SELECT MarketingBudget from Albums WHERE SingerId = 1 and AlbumId = 1'
            );
            $resultsRow = $results->rows()->current();
            $album1budget = $resultsRow['MarketingBudget'];

            $album2budget -= $transferAmount;
            $album1budget += $transferAmount;

            // Update the albums
            $t->executeUpdate(
                'UPDATE Albums '
                . 'SET MarketingBudget = @AlbumBudget '
                . 'WHERE SingerId = 1 and AlbumId = 1',
                [
                    'parameters' => [
                        'AlbumBudget' => $album1budget
                    ]
                ]
            );
            $t->executeUpdate(
                'UPDATE Albums '
                . 'SET MarketingBudget = @AlbumBudget '
                . 'WHERE SingerId = 2 and AlbumId = 2',
                [
                    'parameters' => [
                        'AlbumBudget' => $album2budget
                    ]
                ]
            );

            $t->commit();

            print('Transaction complete.' . PHP_EOL);
        }
    });
}

Jalankan file contoh src/write_data_with_dml_transaction.php.

php src/write_data_with_dml_transaction.php test-instance example-db

Anda akan melihat:

Transaction complete.

Menggunakan indeks sekunder

Misalnya, Anda ingin mengambil semua baris Albums yang memiliki nilai AlbumTitle dalam rentang tertentu. Anda dapat membaca semua nilai dari kolom AlbumTitle menggunakan pernyataan SQL atau panggilan baca, lalu menghapus baris yang tidak memenuhi kriteria, tetapi melakukan pemindaian tabel lengkap ini mahal, terutama untuk tabel dengan banyak baris. Sebagai gantinya, Anda dapat mempercepat pengambilan baris saat menelusuri menurut kolom kunci non-utama dengan membuat indeks sekunder pada tabel.

Menambahkan indeks sekunder ke tabel yang ada memerlukan pembaruan skema. Seperti update skema lainnya, Spanner mendukung penambahan indeks saat database terus menyalurkan traffic. Spanner otomatis mengisi ulang indeks dengan data yang ada. Pengisian ulang mungkin memerlukan waktu beberapa menit untuk selesai, tetapi Anda tidak perlu membuat database offline atau menghindari penulisan ke tabel yang diindeks selama proses ini. Untuk mengetahui detail selengkapnya, lihat Menambahkan indeks sekunder.

Setelah Anda menambahkan indeks sekunder, Spanner akan otomatis menggunakannya untuk kueri SQL yang cenderung berjalan lebih cepat dengan indeks. Jika menggunakan antarmuka baca, Anda harus menentukan indeks yang ingin digunakan.

Menambahkan indeks sekunder

Anda dapat menambahkan indeks di command line menggunakan gcloud CLI atau secara terprogram menggunakan library klien Spanner untuk PHP.

Di command line

Gunakan perintah CREATE INDEX berikut untuk menambahkan indeks ke database:

gcloud spanner databases ddl update example-db --instance=test-instance \
    --ddl='CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)'

Anda akan melihat:

Schema updating...done.

Menggunakan library klien Spanner untuk PHP

Gunakan Database::updateDdl untuk menambahkan indeks:

use Google\Cloud\Spanner\Admin\Database\V1\Client\DatabaseAdminClient;
use Google\Cloud\Spanner\Admin\Database\V1\UpdateDatabaseDdlRequest;

/**
 * Adds a simple index to the example database.
 * Example:
 * ```
 * create_index($projectId, $instanceId, $databaseId);
 * ```
 *
 * @param string $projectId The Google Cloud project ID.
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function create_index(string $projectId, string $instanceId, string $databaseId): void
{
    $databaseAdminClient = new DatabaseAdminClient();
    $databaseName = DatabaseAdminClient::databaseName($projectId, $instanceId, $databaseId);
    $statement = 'CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)';
    $request = new UpdateDatabaseDdlRequest([
        'database' => $databaseName,
        'statements' => [$statement]
    ]);

    $operation = $databaseAdminClient->updateDatabaseDdl($request);

    print('Waiting for operation to complete...' . PHP_EOL);
    $operation->pollUntilComplete();

    printf('Added the AlbumsByAlbumTitle index.' . PHP_EOL);
}

Jalankan file contoh src/create_index.php.

php src/create_index.php test-instance example-db

Menambahkan indeks dapat memerlukan waktu beberapa menit. Setelah indeks ditambahkan, Anda akan melihat:

Added the AlbumsByAlbumTitle index.

Membaca menggunakan indeks

Untuk kueri SQL, Spanner akan otomatis menggunakan indeks yang sesuai. Di antarmuka baca, Anda harus menentukan indeks dalam permintaan.

Untuk menggunakan indeks di antarmuka baca, gunakan metode Database::read.

use Google\Cloud\Spanner\SpannerClient;

/**
 * Reads sample data from the database using an index.
 *
 * The index must exist before running this sample. You can add the index
 * by running the `add_index` sample or by running this DDL statement against
 * your database:
 *
 *     CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)
 *
 * Example:
 * ```
 * read_data_with_index($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function read_data_with_index(string $instanceId, string $databaseId): void
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);
    $database = $instance->database($databaseId);

    $keySet = $spanner->keySet(['all' => true]);
    $results = $database->read(
        'Albums',
        $keySet,
        ['AlbumId', 'AlbumTitle'],
        ['index' => 'AlbumsByAlbumTitle']
    );

    foreach ($results->rows() as $row) {
        printf('AlbumId: %s, AlbumTitle: %s' . PHP_EOL,
            $row['AlbumId'], $row['AlbumTitle']);
    }
}

Jalankan file contoh src/read_data_with_index.php.

php src/read_data_with_index.php test-instance example-db

Anda akan melihat:

AlbumId: 2, AlbumTitle: Forever Hold your Peace
AlbumId: 2, AlbumTitle: Go, Go, Go
AlbumId: 1, AlbumTitle: Green
AlbumId: 3, AlbumTitle: Terrified
AlbumId: 1, AlbumTitle: Total Junk

Menambahkan indeks untuk pembacaan khusus indeks

Anda mungkin telah melihat bahwa contoh pembacaan sebelumnya tidak menyertakan pembacaan kolom MarketingBudget. Hal ini karena antarmuka baca Spanner tidak mendukung kemampuan untuk menggabungkan indeks dengan tabel data untuk mencari nilai yang tidak disimpan dalam indeks.

Buat definisi alternatif AlbumsByAlbumTitle yang menyimpan salinan MarketingBudget dalam indeks.

Di command line

GoogleSQL

gcloud spanner databases ddl update example-db --instance=test-instance \
    --ddl='CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) STORING (MarketingBudget)

PostgreSQL

gcloud spanner databases ddl update example-db --instance=test-instance \
    --ddl='CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) INCLUDE (MarketingBudget)

Menambahkan indeks dapat memerlukan waktu beberapa menit. Setelah indeks ditambahkan, Anda akan melihat:

Schema updating...done.

Menggunakan library klien Spanner untuk PHP

Gunakan Database::updateDdl untuk menambahkan indeks dengan klausa STORING:

use Google\Cloud\Spanner\Admin\Database\V1\Client\DatabaseAdminClient;
use Google\Cloud\Spanner\Admin\Database\V1\UpdateDatabaseDdlRequest;

/**
 * Adds an storing index to the example database.
 *
 * This sample uses the `MarketingBudget` column. You can add the column
 * by running the `add_column` sample or by running this DDL statement against
 * your database:
 *
 *     ALTER TABLE Albums ADD COLUMN MarketingBudget INT64
 *
 * Example:
 * ```
 * create_storing_index($projectId, $instanceId, $databaseId);
 * ```
 *
 * @param string $projectId The Google Cloud project ID.
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function create_storing_index(string $projectId, string $instanceId, string $databaseId): void
{
    $databaseAdminClient = new DatabaseAdminClient();
    $databaseName = DatabaseAdminClient::databaseName($projectId, $instanceId, $databaseId);
    $statement = 'CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) ' .
        'STORING (MarketingBudget)';
    $request = new UpdateDatabaseDdlRequest([
        'database' => $databaseName,
        'statements' => [$statement]
    ]);

    $operation = $databaseAdminClient->updateDatabaseDdl($request);

    print('Waiting for operation to complete...' . PHP_EOL);
    $operation->pollUntilComplete();

    printf('Added the AlbumsByAlbumTitle2 index.' . PHP_EOL);
}

Jalankan file contoh src/create_storing_index.php.

php src/create_storing_index.php test-instance example-db

Anda akan melihat:

Added the AlbumsByAlbumTitle2 index.

Sekarang Anda dapat menjalankan operasi baca yang mengambil semua kolom AlbumId, AlbumTitle, dan MarketingBudget dari indeks AlbumsByAlbumTitle2:

use Google\Cloud\Spanner\SpannerClient;

/**
 * Reads sample data from the database using an index with a storing
 * clause.
 *
 * The index must exist before running this sample. You can add the index
 * by running the `add_storing_index` sample or by running this DDL statement
 * against your database:
 *
 *     CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle)
 *     STORING (MarketingBudget)
 *
 * Example:
 * ```
 * read_data_with_storing_index($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function read_data_with_storing_index(string $instanceId, string $databaseId): void
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);
    $database = $instance->database($databaseId);

    $keySet = $spanner->keySet(['all' => true]);
    $results = $database->read(
        'Albums',
        $keySet,
        ['AlbumId', 'AlbumTitle', 'MarketingBudget'],
        ['index' => 'AlbumsByAlbumTitle2']
    );

    foreach ($results->rows() as $row) {
        printf('AlbumId: %s, AlbumTitle: %s, MarketingBudget: %d' . PHP_EOL,
            $row['AlbumId'], $row['AlbumTitle'], $row['MarketingBudget']);
    }
}

Jalankan file contoh src/read_data_with_storing_index.php.

php src/read_data_with_storing_index.php test-instance example-db

Anda akan melihat output yang mirip dengan:

AlbumId: 2, AlbumTitle: Forever Hold your Peace, MarketingBudget: 300000
AlbumId: 2, AlbumTitle: Go, Go, Go, MarketingBudget: 0
AlbumId: 1, AlbumTitle: Green, MarketingBudget: 0
AlbumId: 3, AlbumTitle: Terrified, MarketingBudget: 0
AlbumId: 1, AlbumTitle: Total Junk, MarketingBudget: 300000

Mengambil data menggunakan transaksi hanya baca

Misalkan Anda ingin menjalankan lebih dari satu operasi baca pada stempel waktu yang sama. Transaksi hanya baca mengamati awalan konsisten dari histori commit transaksi, sehingga aplikasi Anda selalu mendapatkan data yang konsisten. Gunakan objek Snapshot untuk menjalankan transaksi hanya baca. Gunakan metode Database::snapshot untuk mendapatkan objek Snapshot.

Berikut ini cara menjalankan kueri dan melakukan operasi baca dalam transaksi hanya baca yang sama:

use Google\Cloud\Spanner\SpannerClient;

/**
 * Reads data inside of a read-only transaction.
 *
 * Within the read-only transaction, or "snapshot", the application sees
 * consistent view of the database at a particular timestamp.
 * Example:
 * ```
 * read_only_transaction($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function read_only_transaction(string $instanceId, string $databaseId): void
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);
    $database = $instance->database($databaseId);

    $snapshot = $database->snapshot();
    $results = $snapshot->execute(
        'SELECT SingerId, AlbumId, AlbumTitle FROM Albums'
    );
    print('Results from the first read:' . PHP_EOL);
    foreach ($results as $row) {
        printf('SingerId: %s, AlbumId: %s, AlbumTitle: %s' . PHP_EOL,
            $row['SingerId'], $row['AlbumId'], $row['AlbumTitle']);
    }

    // Perform another read using the `read` method. Even if the data
    // is updated in-between the reads, the snapshot ensures that both
    // return the same data.
    $keySet = $spanner->keySet(['all' => true]);
    $results = $database->read(
        'Albums',
        $keySet,
        ['SingerId', 'AlbumId', 'AlbumTitle']
    );

    print('Results from the second read:' . PHP_EOL);
    foreach ($results->rows() as $row) {
        printf('SingerId: %s, AlbumId: %s, AlbumTitle: %s' . PHP_EOL,
            $row['SingerId'], $row['AlbumId'], $row['AlbumTitle']);
    }
}

Jalankan file contoh src/read_only_transaction.php.

php src/read_only_transaction.php test-instance example-db

Anda akan melihat output yang mirip dengan:

Results from first read:
SingerId: 2, AlbumId: 2, AlbumTitle: Forever Hold Your Peace
SingerId: 1, AlbumId: 2, AlbumTitle: Go, Go, Go
SingerId: 2, AlbumId: 1, AlbumTitle: Green
SingerId: 2, AlbumId: 3, AlbumTitle: Terrified
SingerId: 1, AlbumId: 1, AlbumTitle: Total Junk
Results from second read:
SingerId: 1, AlbumId: 1, AlbumTitle: Total Junk
SingerId: 1, AlbumId: 2, AlbumTitle: Go, Go, Go
SingerId: 2, AlbumId: 1, AlbumTitle: Green
SingerId: 2, AlbumId: 2, AlbumTitle: Forever Hold Your Peace
SingerId: 2, AlbumId: 3, AlbumTitle: Terrified

Pembersihan

Agar tidak menimbulkan biaya tambahan pada akun Penagihan Cloud untuk resource yang digunakan dalam tutorial ini, hapus database dan instance yang Anda buat.

Menghapus database

Jika Anda menghapus instance, semua database di dalamnya akan otomatis dihapus. Langkah ini menunjukkan cara menghapus database tanpa menghapus instance (Anda akan tetap dikenai biaya untuk instance).

Di command line

gcloud spanner databases delete example-db --instance=test-instance

Menggunakan konsol Google Cloud

  1. Buka halaman Spanner Instances di konsol Google Cloud.

    Buka halaman Instances

  2. Klik instance.

  3. Klik database yang ingin dihapus.

  4. Di halaman Database details, klik Delete.

  5. Konfirmasi bahwa Anda ingin menghapus database, lalu klik Hapus.

Menghapus instance

Menghapus instance akan otomatis menghapus semua database yang dibuat di instance tersebut.

Di command line

gcloud spanner instances delete test-instance

Menggunakan konsol Google Cloud

  1. Buka halaman Spanner Instances di konsol Google Cloud.

    Buka halaman Instances

  2. Klik instance Anda.

  3. Klik Hapus.

  4. Konfirmasi bahwa Anda ingin menghapus instance, lalu klik Hapus.

Langkah selanjutnya