1. Ringkasan
Google Cloud Spanner adalah layanan database relasional skalabel dan terkelola sepenuhnya secara global yang menyediakan transaksi ACID dan semantik SQL tanpa merusak performa dan ketersediaan yang tinggi.
Di lab ini, Anda akan mempelajari cara menyiapkan instance Cloud Spanner. Anda akan menjalani langkah-langkah untuk membuat database dan skema yang dapat digunakan untuk papan peringkat game. Anda akan mulai dengan membuat tabel Pemain untuk menyimpan informasi pemain dan tabel Skor untuk menyimpan skor pemain.
Selanjutnya, Anda akan mengisi tabel dengan data contoh. Kemudian Anda akan mengakhiri lab dengan menjalankan kueri contoh Sepuluh Teratas dan menghapus instance untuk mengosongkan resource.
Yang akan Anda pelajari
- Cara menyiapkan instance Cloud Spanner.
- Cara membuat database dan tabel.
- Cara menggunakan kolom stempel waktu commit.
- Cara memuat data ke tabel database Cloud Spanner dengan stempel waktu.
- Cara membuat kueri database Cloud Spanner.
- Cara menghapus instance Cloud Spanner.
Yang Anda perlukan
Bagaimana Anda akan menggunakan tutorial ini?
Bagaimana Anda menilai pengalaman Anda dengan Google Cloud Platform?
2. Penyiapan dan Persyaratan
Penyiapan lingkungan mandiri
Jika belum memiliki Akun Google (Gmail atau Google Apps), Anda harus membuatnya. Login ke Google Cloud Platform console (console.cloud.google.com) dan buat project baru.
Jika Anda sudah memiliki project, klik menu pull-down pilihan project di kiri atas konsol:
dan klik tombol 'PROJECT BARU' dalam dialog yang dihasilkan untuk membuat project baru:
Jika belum memiliki project, Anda akan melihat dialog seperti ini untuk membuat project pertama:
Dialog pembuatan project berikutnya memungkinkan Anda memasukkan detail project baru:
Ingat project ID yang merupakan nama unik di semua project Google Cloud (maaf, nama di atas telah digunakan dan tidak akan berfungsi untuk Anda!) Project ID tersebut selanjutnya akan dirujuk di codelab ini sebagai PROJECT_ID
.
Selanjutnya, jika Anda belum melakukannya, Anda harus mengaktifkan penagihan di Developers Console untuk menggunakan resource Google Cloud dan mengaktifkan Cloud Spanner API.
Menjalankan melalui codelab ini tidak akan menghabiskan biaya lebih dari beberapa dolar, tetapi bisa lebih jika Anda memutuskan untuk menggunakan lebih banyak resource atau jika Anda membiarkannya berjalan (lihat bagian "pembersihan" di akhir dokumen ini). Harga Google Cloud Spanner didokumentasikan di sini.
Pengguna baru Google Cloud Platform memenuhi syarat untuk mendapatkan uji coba gratis senilai $300, yang menjadikan codelab ini sepenuhnya gratis.
Penyiapan Google Cloud Shell
Meskipun Google Cloud dan Spanner dapat dioperasikan dari jarak jauh menggunakan laptop Anda, dalam codelab ini, kita akan menggunakan Google Cloud Shell, lingkungan command line yang berjalan di Cloud.
Mesin virtual berbasis Debian ini memuat semua alat pengembangan yang akan Anda perlukan. Layanan ini menawarkan direktori beranda tetap sebesar 5 GB dan beroperasi di Google Cloud, sehingga sangat meningkatkan performa dan autentikasi jaringan. Ini berarti bahwa semua yang Anda perlukan untuk codelab ini adalah browser (ya, ini berfungsi di Chromebook).
- Untuk mengaktifkan Cloud Shell dari Cloud Console, cukup klik Aktifkan Cloud Shell (hanya perlu beberapa saat untuk melakukan penyediaan dan terhubung ke lingkungan).
Setelah terhubung ke Cloud Shell, Anda akan melihat bahwa Anda sudah diautentikasi dan project sudah ditetapkan ke PROJECT_ID
.
gcloud auth list
Output perintah
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
Output perintah
[core] project = <PROJECT_ID>
Jika, untuk beberapa alasan, project belum disetel, cukup jalankan perintah berikut:
gcloud config set project <PROJECT_ID>
Mencari PROJECT_ID
Anda? Periksa ID yang Anda gunakan di langkah-langkah penyiapan atau cari di dasbor Cloud Console:
Cloud Shell juga menetapkan beberapa variabel lingkungan secara default, yang mungkin berguna saat Anda menjalankan perintah di masa mendatang.
echo $GOOGLE_CLOUD_PROJECT
Output perintah
<PROJECT_ID>
- Terakhir, tetapkan zona dan konfigurasi project default.
gcloud config set compute/zone us-central1-f
Anda dapat memilih berbagai zona yang berbeda. Untuk informasi selengkapnya, lihat Region & Zona.
Ringkasan
Pada langkah ini, Anda menyiapkan lingkungan.
Berikutnya
Selanjutnya, Anda akan menyiapkan Instance Cloud Spanner.
3. Menyiapkan Instance Cloud Spanner
Pada langkah ini kita menyiapkan Instance Cloud Spanner untuk codelab ini. Telusuri entri Spanner di kiri atas Menu Tiga Garis atau telusuri Spanner dengan menekan "/" dan ketik "Spanner"
Selanjutnya, klik dan isi formulir dengan memasukkan nama instance cloudspanner-leaderboard untuk instance Anda, memilih konfigurasi (pilih instance regional), dan menetapkan jumlah node, untuk codelab ini kita hanya perlu 1 node. Agar instance produksi dan untuk memenuhi syarat untuk SLA Cloud Spanner, Anda harus menjalankan 3 node atau lebih di instance Cloud Spanner.
Terakhir, namun tidak kalah penting, klik "Buat" dan dalam beberapa detik Anda sudah memiliki instance Cloud Spanner.
Pada langkah berikutnya, kita akan menggunakan library klien C# untuk membuat database dan skema di instance baru.
4. Membuat database dan skema
Pada langkah ini, kita akan membuat contoh database dan skema.
Mari kita gunakan {i>library<i} klien C# untuk membuat dua tabel; tabel Pemain untuk info pemain dan tabel Skor untuk menyimpan skor pemain. Untuk melakukannya, kita akan memandu langkah-langkah pembuatan aplikasi konsol C# di Cloud Shell.
Pertama-tama, clone kode sampel untuk codelab ini dari GitHub dengan mengetik perintah berikut di Cloud Shell:
git clone https://github.com/GoogleCloudPlatform/dotnet-docs-samples.git
Kemudian, ubah direktori ke direktori "aplikasi" tempat Anda akan membuat aplikasi.
cd dotnet-docs-samples/applications/
Semua kode yang diperlukan untuk codelab ini terletak di direktori dotnet-docs-samples/applications/leaderboard
yang ada sebagai aplikasi Go yaC# dapat dijalankan dengan nama Leaderboard
untuk berfungsi sebagai referensi saat Anda melanjutkan codelab. Kami akan membuat direktori baru dan mem-build salinan aplikasi Papan Peringkat secara bertahap.
Buat direktori baru bernama "codelab" untuk aplikasi dan ubah direktori menjadi papan peringkat dengan perintah berikut:
mkdir codelab && cd $_
Buat aplikasi konsol C# .NET baru bernama "Leaderboard" menggunakan perintah berikut:
dotnet new console -n Leaderboard
Perintah ini membuat aplikasi konsol sederhana yang terdiri dari dua file utama, file project Leaderboard.csproj
dan file program Program.cs
.
Jalankan kueri. Ubah direktori ke direktori Papan Peringkat yang baru dibuat tempat aplikasi berada:
cd Leaderboard
Kemudian masukkan perintah berikut untuk menjalankannya.
dotnet run
Anda akan melihat output aplikasi "Hello World!".
Sekarang mari kita update aplikasi konsol dengan mengedit Program.cs
untuk menggunakan library klien C# Spanner untuk membuat papan peringkat yang terdiri dari dua tabel, Pemain dan Skor. Anda dapat melakukannya langsung di Cloud Shell Editor:
Buka Cloud Shell Editor, dengan mengklik ikon yang disorot di bawah:
Selanjutnya, buka file Program.cs
di Cloud Shell Editor dan ganti kode file yang ada dengan kode yang diperlukan untuk membuat database leaderboard
serta tabel Players
dan Scores
dengan menempelkan kode aplikasi C# berikut ke dalam file Program.cs
:
using System;
using System.Threading.Tasks;
using Google.Cloud.Spanner.Data;
using CommandLine;
namespace GoogleCloudSamples.Leaderboard
{
[Verb("create", HelpText = "Create a sample Cloud Spanner database "
+ "along with sample 'Players' and 'Scores' tables in your project.")]
class CreateOptions
{
[Value(0, HelpText = "The project ID of the project to use "
+ "when creating Cloud Spanner resources.", Required = true)]
public string projectId { get; set; }
[Value(1, HelpText = "The ID of the instance where the sample database "
+ "will be created.", Required = true)]
public string instanceId { get; set; }
[Value(2, HelpText = "The ID of the sample database to create.",
Required = true)]
public string databaseId { get; set; }
}
public class Program
{
enum ExitCode : int
{
Success = 0,
InvalidParameter = 1,
}
public static object Create(string projectId,
string instanceId, string databaseId)
{
var response =
CreateAsync(projectId, instanceId, databaseId);
Console.WriteLine("Waiting for operation to complete...");
response.Wait();
Console.WriteLine($"Operation status: {response.Status}");
Console.WriteLine($"Created sample database {databaseId} on "
+ $"instance {instanceId}");
return ExitCode.Success;
}
public static async Task CreateAsync(
string projectId, string instanceId, string databaseId)
{
// Initialize request connection string for database creation.
string connectionString =
$"Data Source=projects/{projectId}/instances/{instanceId}";
using (var connection = new SpannerConnection(connectionString))
{
string createStatement = $"CREATE DATABASE `{databaseId}`";
string[] createTableStatements = new string[] {
// Define create table statement for Players table.
@"CREATE TABLE Players(
PlayerId INT64 NOT NULL,
PlayerName STRING(2048) NOT NULL
) PRIMARY KEY(PlayerId)",
// Define create table statement for Scores table.
@"CREATE TABLE Scores(
PlayerId INT64 NOT NULL,
Score INT64 NOT NULL,
Timestamp TIMESTAMP NOT NULL OPTIONS(allow_commit_timestamp=true)
) PRIMARY KEY(PlayerId, Timestamp),
INTERLEAVE IN PARENT Players ON DELETE NO ACTION" };
// Make the request.
var cmd = connection.CreateDdlCommand(
createStatement, createTableStatements);
try
{
await cmd.ExecuteNonQueryAsync();
}
catch (SpannerException e) when
(e.ErrorCode == ErrorCode.AlreadyExists)
{
// OK.
}
}
}
public static int Main(string[] args)
{
var verbMap = new VerbMap<object>();
verbMap
.Add((CreateOptions opts) => Create(
opts.projectId, opts.instanceId, opts.databaseId))
.NotParsedFunc = (err) => 1;
return (int)verbMap.Run(args);
}
}
}
Untuk memberikan gambaran yang lebih jelas tentang kode Program, berikut ini diagram Program dengan komponen utamanya yang diberi label:
Anda dapat menggunakan file Program.cs
di direktori dotnet-docs-samples/applications/leaderboard/step4
untuk melihat contoh tampilan file Program.cs
setelah menambahkan kode untuk mengaktifkan perintah create
.
Selanjutnya, gunakan Cloud Shell Editor untuk membuka dan mengedit file project Program Leaderboard.csproj
, dengan memperbaruinya agar terlihat seperti kode berikut. Pastikan Anda menyimpan semua perubahan menggunakan "File" menu Cloud Shell Editor.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.Cloud.Spanner.Data" Version="3.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\commandlineutil\Lib\CommandLineUtil.csproj" />
</ItemGroup>
</Project>
Perubahan ini menambahkan referensi ke paket Nuget C# Spanner Google.Cloud.Spanner.Data
yang diperlukan untuk berinteraksi dengan Cloud Spanner API. Perubahan ini juga menambahkan referensi ke project CommandLineUtil
yang merupakan bagian dari repositori GitHub dotnet-doc-samples dan memberikan "verbmap" yang berguna ekstensi ke CommandLineParser
{i>open source<i}; pustaka praktis untuk menangani input baris
perintah untuk aplikasi konsol.
Anda dapat menggunakan file Leaderboard.csproj
di direktori dotnet-docs-samples/applications/leaderboard/step4
untuk melihat contoh tampilan file Leaderboard.csproj
setelah menambahkan kode untuk mengaktifkan perintah create
.
Sekarang Anda siap menjalankan contoh yang telah diperbarui. Ketik perintah berikut untuk melihat respons default dari aplikasi Anda yang diupdate:
dotnet run
Anda akan melihat output seperti berikut:
Leaderboard 1.0.0 Copyright (C) 2018 Leaderboard ERROR(S): No verb selected. create Create a sample Cloud Spanner database along with sample 'Players' and 'Scores' tables in your project. help Display more information on a specific command. version Display version information.
Dari respons ini, kita dapat melihat bahwa ini adalah aplikasi Leaderboard
yang dapat dijalankan dengan salah satu dari tiga kemungkinan perintah: create
, help
, dan version
.
Mari kita coba perintah create
untuk membuat database dan tabel Spanner. Jalankan perintah tanpa argumen untuk melihat argumen yang diharapkan dari perintah tersebut.
dotnet run create
Anda akan melihat respons seperti berikut:
Leaderboard 1.0.0 Copyright (C) 2018 Leaderboard ERROR(S): A required value not bound to option name is missing. --help Display this help screen. --version Display version information. value pos. 0 Required. The project ID of the project to use when creating Cloud Spanner resources. value pos. 1 Required. The ID of the instance where the sample database will be created. value pos. 2 Required. The ID of the sample database to create.
Di sini kita dapat melihat bahwa argumen yang diharapkan dari perintah create
adalah Project ID, Instance ID, dan Database ID.
Sekarang jalankan perintah berikut. Pastikan Anda mengganti PROJECT_ID
dengan Project ID yang Anda buat di awal codelab ini.
dotnet run create PROJECT_ID cloudspanner-leaderboard leaderboard
Setelah beberapa detik, Anda akan melihat respons seperti berikut:
Waiting for operation to complete... Operation status: RanToCompletion Created sample database leaderboard on instance cloudspanner-leaderboard
Di bagian Cloud Spanner pada Cloud Console, Anda akan melihat database dan tabel baru muncul di menu sebelah kiri.
Pada langkah berikutnya, kita akan mengupdate aplikasi untuk memuat beberapa data ke database baru Anda.
5. Muat Data
Sekarang kita memiliki database yang disebut leaderboard
yang berisi dua tabel; Players
dan Scores
Sekarang mari kita gunakan library klien C# untuk mengisi tabel Players
dengan pemain dan tabel Scores
dengan skor acak untuk setiap pemain.
Buka Cloud Shell Editor, dengan mengklik ikon yang disorot di bawah:
Selanjutnya, edit file Program.cs
di Cloud Shell Editor untuk menambahkan perintah insert
yang dapat digunakan untuk menyisipkan 100 pemain ke dalam tabel Players
atau dapat digunakan untuk menyisipkan 4 skor acak di tabel Scores
untuk setiap pemain di tabel Players
.
Pertama, tambahkan blok perintah insert
baru di "Verbmap" di bagian atas Program di bawah blok perintah create
yang ada:
[Verb("insert", HelpText = "Insert sample 'players' records or 'scores' records "
+ "into the database.")]
class InsertOptions
{
[Value(0, HelpText = "The project ID of the project to use "
+ "when managing Cloud Spanner resources.", Required = true)]
public string projectId { get; set; }
[Value(1, HelpText = "The ID of the instance where the sample database resides.",
Required = true)]
public string instanceId { get; set; }
[Value(2, HelpText = "The ID of the database where the sample database resides.",
Required = true)]
public string databaseId { get; set; }
[Value(3, HelpText = "The type of insert to perform, 'players' or 'scores'.",
Required = true)]
public string insertType { get; set; }
}
Selanjutnya, tambahkan metode Insert
, InsertPlayersAsync
, dan InsertScoresAsync
berikut di bawah metode CreateAsync
yang ada:
public static object Insert(string projectId,
string instanceId, string databaseId, string insertType)
{
if (insertType.ToLower() == "players")
{
var responseTask =
InsertPlayersAsync(projectId, instanceId, databaseId);
Console.WriteLine("Waiting for insert players operation to complete...");
responseTask.Wait();
Console.WriteLine($"Operation status: {responseTask.Status}");
}
else if (insertType.ToLower() == "scores")
{
var responseTask =
InsertScoresAsync(projectId, instanceId, databaseId);
Console.WriteLine("Waiting for insert scores operation to complete...");
responseTask.Wait();
Console.WriteLine($"Operation status: {responseTask.Status}");
}
else
{
Console.WriteLine("Invalid value for 'type of insert'. "
+ "Specify 'players' or 'scores'.");
return ExitCode.InvalidParameter;
}
Console.WriteLine($"Inserted {insertType} into sample database "
+ $"{databaseId} on instance {instanceId}");
return ExitCode.Success;
}
public static async Task InsertPlayersAsync(string projectId,
string instanceId, string databaseId)
{
string connectionString =
$"Data Source=projects/{projectId}/instances/{instanceId}"
+ $"/databases/{databaseId}";
long numberOfPlayers = 0;
using (var connection = new SpannerConnection(connectionString))
{
await connection.OpenAsync();
await connection.RunWithRetriableTransactionAsync(async (transaction) =>
{
// Execute a SQL statement to get current number of records
// in the Players table to use as an incrementing value
// for each PlayerName to be inserted.
var cmd = connection.CreateSelectCommand(
@"SELECT Count(PlayerId) as PlayerCount FROM Players");
numberOfPlayers = await cmd.ExecuteScalarAsync<long>();
// Insert 100 player records into the Players table.
SpannerBatchCommand cmdBatch = connection.CreateBatchDmlCommand();
for (int i = 0; i < 100; i++)
{
numberOfPlayers++;
SpannerCommand cmdInsert = connection.CreateDmlCommand(
"INSERT INTO Players "
+ "(PlayerId, PlayerName) "
+ "VALUES (@PlayerId, @PlayerName)",
new SpannerParameterCollection {
{"PlayerId", SpannerDbType.Int64},
{"PlayerName", SpannerDbType.String}});
cmdInsert.Parameters["PlayerId"].Value =
Math.Abs(Guid.NewGuid().GetHashCode());
cmdInsert.Parameters["PlayerName"].Value =
$"Player {numberOfPlayers}";
cmdBatch.Add(cmdInsert);
}
await cmdBatch.ExecuteNonQueryAsync();
});
}
Console.WriteLine("Done inserting player records...");
}
public static async Task InsertScoresAsync(
string projectId, string instanceId, string databaseId)
{
string connectionString =
$"Data Source=projects/{projectId}/instances/{instanceId}"
+ $"/databases/{databaseId}";
// Insert 4 score records into the Scores table for each player
// in the Players table.
using (var connection = new SpannerConnection(connectionString))
{
await connection.OpenAsync();
await connection.RunWithRetriableTransactionAsync(async (transaction) =>
{
Random r = new Random();
bool playerRecordsFound = false;
SpannerBatchCommand cmdBatch =
connection.CreateBatchDmlCommand();
var cmdLookup =
connection.CreateSelectCommand("SELECT * FROM Players");
using (var reader = await cmdLookup.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
playerRecordsFound = true;
for (int i = 0; i < 4; i++)
{
DateTime randomTimestamp = DateTime.Now
.AddYears(r.Next(-2, 1))
.AddMonths(r.Next(-12, 1))
.AddDays(r.Next(-28, 0))
.AddHours(r.Next(-24, 0))
.AddSeconds(r.Next(-60, 0))
.AddMilliseconds(r.Next(-100000, 0));
SpannerCommand cmdInsert =
connection.CreateDmlCommand(
"INSERT INTO Scores "
+ "(PlayerId, Score, Timestamp) "
+ "VALUES (@PlayerId, @Score, @Timestamp)",
new SpannerParameterCollection {
{"PlayerId", SpannerDbType.Int64},
{"Score", SpannerDbType.Int64},
{"Timestamp",
SpannerDbType.Timestamp}});
cmdInsert.Parameters["PlayerId"].Value =
reader.GetFieldValue<int>("PlayerId");
cmdInsert.Parameters["Score"].Value =
r.Next(1000, 1000001);
cmdInsert.Parameters["Timestamp"].Value =
randomTimestamp.ToString("o");
cmdBatch.Add(cmdInsert);
}
}
if (!playerRecordsFound)
{
Console.WriteLine("Parameter 'scores' is invalid "
+ "since no player records currently exist. First "
+ "insert players then insert scores.");
Environment.Exit((int)ExitCode.InvalidParameter);
}
else
{
await cmdBatch.ExecuteNonQueryAsync();
Console.WriteLine(
"Done inserting score records..."
);
}
}
});
}
}
Kemudian, untuk membuat perintah insert
berfungsi, tambahkan kode berikut ke kolom "Utama" Program Anda berikut:
.Add((InsertOptions opts) => Insert(
opts.projectId, opts.instanceId, opts.databaseId, opts.insertType))
Anda dapat menggunakan file Program.cs
di direktori dotnet-docs-samples/applications/leaderboard/step5
untuk melihat contoh tampilan file Program.cs
setelah menambahkan kode untuk mengaktifkan perintah insert
.
Sekarang, mari kita jalankan program untuk mengonfirmasi bahwa perintah insert
baru disertakan dalam daftar kemungkinan perintah program. Jalankan perintah berikut:
dotnet run
Anda akan melihat perintah insert
kini disertakan dalam output default program:
Leaderboard 1.0.0 Copyright (C) 2018 Leaderboard ERROR(S): No verb selected. create Create a sample Cloud Spanner database along with sample 'Players' and 'Scores' tables in your project. insert Insert sample 'players' records or 'scores' records into the database. help Display more information on a specific command. version Display version information.
Sekarang, mari kita jalankan perintah insert
untuk melihat argumen inputnya. Masukkan perintah berikut.
dotnet run insert
Respons yang ditampilkan akan seperti ini:
Leaderboard 1.0.0 Copyright (C) 2018 Leaderboard ERROR(S): A required value not bound to option name is missing. --help Display this help screen. --version Display version information. value pos. 0 Required. The project ID of the project to use when managing Cloud Spanner resources. value pos. 1 Required. The ID of the instance where the sample database resides. value pos. 2 Required. The ID of the database where the sample database resides. value pos. 3 Required. The type of insert to perform, 'players' or 'scores'.
Anda dapat melihat dari respons bahwa selain Project ID, ID Instance, dan ID Database, ada argumen lain value pos. 3
yang diharapkan, yaitu "jenis penyisipan" untuk dilakukan. Argumen ini dapat memiliki nilai 'players' atau ‘skor’.
Sekarang, mari kita jalankan perintah insert
dengan nilai argumen yang sama dengan yang digunakan saat kita memanggil perintah create
, menambahkan "pemain" sebagai argumen "type of insert" tambahan. Pastikan Anda mengganti PROJECT_ID
dengan Project ID yang Anda buat di awal codelab ini.
dotnet run insert PROJECT_ID cloudspanner-leaderboard leaderboard players
Setelah beberapa detik, Anda akan melihat respons seperti berikut:
Waiting for insert players operation to complete... Done inserting player records... Operation status: RanToCompletion Inserted players into sample database leaderboard on instance cloudspanner-leaderboard
Sekarang, mari kita gunakan library klien C# untuk mengisi tabel Scores
dengan empat skor acak beserta stempel waktu untuk setiap pemain di tabel Players
.
Kolom Timestamp
pada tabel Scores
ditetapkan sebagai kolom "stempel waktu commit" melalui pernyataan SQL berikut yang dijalankan saat sebelumnya menjalankan perintah create
:
CREATE TABLE Scores(
PlayerId INT64 NOT NULL,
Score INT64 NOT NULL,
Timestamp TIMESTAMP NOT NULL OPTIONS(allow_commit_timestamp=true)
) PRIMARY KEY(PlayerId, Timestamp),
INTERLEAVE IN PARENT Players ON DELETE NO ACTION
Perhatikan atribut OPTIONS(allow_commit_timestamp=true)
. Ini membuat Timestamp
menjadi kolom "stempel waktu commit" dan mengaktifkannya untuk diisi secara otomatis dengan stempel waktu transaksi yang tepat untuk operasi INSERT dan UPDATE pada baris tabel tertentu.
Anda juga dapat menyisipkan nilai stempel waktu Anda sendiri ke dalam kolom "stempel waktu commit" selama Anda menyisipkan stempel waktu dengan nilai yang sudah berlalu, yang akan kita lakukan untuk tujuan codelab ini.
Sekarang, mari kita jalankan perintah insert
dengan nilai argumen yang sama dengan yang digunakan saat kita memanggil perintah create
, menambahkan "skor" sebagai argumen "type of insert" tambahan. Pastikan Anda mengganti PROJECT_ID
dengan Project ID yang Anda buat di awal codelab ini.
dotnet run insert PROJECT_ID cloudspanner-leaderboard leaderboard scores
Setelah beberapa detik, Anda akan melihat respons seperti berikut:
Waiting for insert players operation to complete... Done inserting player records... Operation status: RanToCompletion Inserted players into sample database leaderboard on instance cloudspanner-leaderboard
Menjalankan insert
dengan "type of insert" yang ditentukan sebagai scores
memanggil metode InsertScoresAsync
yang menggunakan cuplikan kode berikut untuk menyisipkan stempel waktu yang dibuat secara acak dengan tanggal-waktu yang terjadi di waktu lampau:
DateTime randomTimestamp = DateTime.Now
.AddYears(r.Next(-2, 1))
.AddMonths(r.Next(-12, 1))
.AddDays(r.Next(-28, 0))
.AddHours(r.Next(-24, 0))
.AddSeconds(r.Next(-60, 0))
.AddMilliseconds(r.Next(-100000, 0));
...
cmdInsert.Parameters["Timestamp"].Value = randomTimestamp.ToString("o");
Untuk mengisi otomatis kolom Timestamp
dengan stempel waktu tepat saat tombol "Sisipkan" berlangsung, Anda dapat menyisipkan konstanta C# SpannerParameter.CommitTimestamp
seperti dalam cuplikan kode berikut:
cmd.Parameters["Timestamp"].Value = SpannerParameter.CommitTimestamp;
Setelah menyelesaikan pemuatan data, mari kita verifikasi nilai yang baru saja kita tulis ke tabel baru. Pertama-tama, pilih database leaderboard
, lalu pilih tabel Players
. Klik tab Data
. Anda akan melihat bahwa Anda memiliki data di kolom PlayerId
dan PlayerName
tabel.
Selanjutnya, pastikan tabel Skor juga memiliki data dengan mengklik tabel Scores
dan memilih tab Data
. Anda akan melihat bahwa Anda memiliki data di kolom PlayerId
, Timestamp
, dan Score
tabel.
Bagus! Mari kita perbarui Program untuk menjalankan beberapa kueri yang dapat kita gunakan untuk membuat papan peringkat game.
6. Menjalankan kueri papan peringkat
Setelah menyiapkan database dan memuat informasi ke dalam tabel, mari kita buat papan peringkat menggunakan data ini. Untuk melakukannya, kita harus menjawab empat pertanyaan berikut:
- Pemain mana yang masuk peringkat "Sepuluh Teratas" sepanjang waktu?
- Pemain mana yang masuk peringkat "Sepuluh Teratas" tahun ini?
- Pemain mana yang masuk peringkat "Sepuluh Teratas" bulan ini?
- Pemain mana yang masuk peringkat "Sepuluh Teratas" minggu ini?
Mari kita perbarui Program untuk menjalankan kueri SQL yang akan menjawab pertanyaan ini.
Kita akan menambahkan perintah query
yang akan memberikan cara untuk menjalankan kueri guna menjawab pertanyaan yang akan menghasilkan informasi yang diperlukan untuk papan peringkat.
Edit file Program.cs
di Cloud Shell Editor untuk mengupdate Program agar dapat menambahkan perintah query
.
Pertama, tambahkan blok perintah query
baru di "Verbmap" di bagian atas Program di bawah blok perintah insert
yang ada:
[Verb("query", HelpText = "Query players with 'Top Ten' scores within a specific timespan "
+ "from sample Cloud Spanner database table.")]
class QueryOptions
{
[Value(0, HelpText = "The project ID of the project to use "
+ "when managing Cloud Spanner resources.", Required = true)]
public string projectId { get; set; }
[Value(1, HelpText = "The ID of the instance where the sample data resides.",
Required = true)]
public string instanceId { get; set; }
[Value(2, HelpText = "The ID of the database where the sample data resides.",
Required = true)]
public string databaseId { get; set; }
[Value(3, Default = 0, HelpText = "The timespan in hours that will be used to filter the "
+ "results based on a record's timestamp. The default will return the "
+ "'Top Ten' scores of all time.")]
public int timespan { get; set; }
}
Selanjutnya, tambahkan metode Query
dan QueryAsync
berikut di bawah metode InsertScoresAsync
yang ada:
public static object Query(string projectId,
string instanceId, string databaseId, int timespan)
{
var response = QueryAsync(
projectId, instanceId, databaseId, timespan);
response.Wait();
return ExitCode.Success;
}
public static async Task QueryAsync(
string projectId, string instanceId, string databaseId, int timespan)
{
string connectionString =
$"Data Source=projects/{projectId}/instances/"
+ $"{instanceId}/databases/{databaseId}";
// Create connection to Cloud Spanner.
using (var connection = new SpannerConnection(connectionString))
{
string sqlCommand;
if (timespan == 0)
{
// No timespan specified. Query Top Ten scores of all time.
sqlCommand =
@"SELECT p.PlayerId, p.PlayerName, s.Score, s.Timestamp
FROM Players p
JOIN Scores s ON p.PlayerId = s.PlayerId
ORDER BY s.Score DESC LIMIT 10";
}
else
{
// Query Top Ten scores filtered by the timepan specified.
sqlCommand =
$@"SELECT p.PlayerId, p.PlayerName, s.Score, s.Timestamp
FROM Players p
JOIN Scores s ON p.PlayerId = s.PlayerId
WHERE s.Timestamp >
TIMESTAMP_SUB(CURRENT_TIMESTAMP(),
INTERVAL {timespan.ToString()} HOUR)
ORDER BY s.Score DESC LIMIT 10";
}
var cmd = connection.CreateSelectCommand(sqlCommand);
using (var reader = await cmd.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
Console.WriteLine("PlayerId : "
+ reader.GetFieldValue<string>("PlayerId")
+ " PlayerName : "
+ reader.GetFieldValue<string>("PlayerName")
+ " Score : "
+ string.Format("{0:n0}",
Int64.Parse(reader.GetFieldValue<string>("Score")))
+ " Timestamp : "
+ reader.GetFieldValue<string>("Timestamp").Substring(0, 10));
}
}
}
}
Kemudian, untuk membuat perintah query
berfungsi, tambahkan kode berikut ke kolom "Utama" Program Anda berikut:
.Add((QueryOptions opts) => Query(
opts.projectId, opts.instanceId, opts.databaseId, opts.timespan))
Anda dapat menggunakan file Program.cs
di direktori dotnet-docs-samples/applications/leaderboard/step6
untuk melihat contoh tampilan file Program.cs
setelah menambahkan kode untuk mengaktifkan perintah query
.
Sekarang, mari kita jalankan program untuk mengonfirmasi bahwa perintah query
baru disertakan dalam daftar kemungkinan perintah program. Jalankan perintah berikut:
dotnet run
Anda akan melihat perintah query
kini disertakan dalam output default program sebagai opsi perintah baru:
Leaderboard 1.0.0 Copyright (C) 2018 Leaderboard ERROR(S): No verb selected. create Create a sample Cloud Spanner database along with sample 'Players' and 'Scores' tables in your project. insert Insert sample 'players' records or 'scores' records into the database. query Query players with 'Top Ten' scores within a specific timespan from sample Cloud Spanner database table. help Display more information on a specific command. version Display version information.
Sekarang, mari kita jalankan perintah query
untuk melihat argumen inputnya. Masukkan perintah berikut:
dotnet run query
Ini akan mengembalikan respons berikut:
Leaderboard 1.0.0 Copyright (C) 2018 Leaderboard ERROR(S): A required value not bound to option name is missing. --help Display this help screen. --version Display version information. value pos. 0 Required. The project ID of the project to use when managing Cloud Spanner resources. value pos. 1 Required. The ID of the instance where the sample data resides. value pos. 2 Required. The ID of the database where the sample data resides. value pos. 3 (Default: 0) The timespan in hours that will be used to filter the results based on a record's timestamp. The default will return the 'Top Ten' scores of all time.
Anda dapat melihat dari respons bahwa selain Project ID, ID Instance, dan ID Database, ada argumen lain value pos. 3
yang diharapkan, yang memungkinkan kita menentukan rentang waktu dalam jumlah jam yang akan digunakan untuk memfilter kumpulan data berdasarkan nilainya di kolom Timestamp
pada tabel Scores
. Argumen ini memiliki nilai default 0, yang berarti tidak ada kumpulan data yang akan difilter menurut stempel waktu. Jadi kita bisa menggunakan perintah query
tanpa nilai "timespan" untuk mendapatkan daftar pemain "Sepuluh Teratas" sepanjang masa.
Mari kita jalankan perintah query
tanpa menetapkan "timespan", menggunakan nilai argumen yang sama dengan yang digunakan saat menjalankan perintah create
. Pastikan Anda mengganti PROJECT_ID
dengan Project ID yang Anda buat di awal codelab ini.
dotnet run query PROJECT_ID cloudspanner-leaderboard leaderboard
Anda akan melihat respons yang menyertakan pemain "Sepuluh Teratas" sepanjang masa seperti berikut:
PlayerId : 1843159180 PlayerName : Player 87 Score : 998,955 Timestamp : 2016-03-23
PlayerId : 61891198 PlayerName : Player 19 Score : 998,720 Timestamp : 2016-03-26
PlayerId : 340906298 PlayerName : Player 48 Score : 993,302 Timestamp : 2015-08-27
PlayerId : 541473117 PlayerName : Player 22 Score : 991,368 Timestamp : 2018-04-30
PlayerId : 857460496 PlayerName : Player 68 Score : 988,010 Timestamp : 2015-05-25
PlayerId : 1826646419 PlayerName : Player 91 Score : 984,022 Timestamp : 2016-11-26
PlayerId : 1002199735 PlayerName : Player 35 Score : 982,933 Timestamp : 2015-09-26
PlayerId : 2002563755 PlayerName : Player 23 Score : 979,041 Timestamp : 2016-10-25
PlayerId : 1377548191 PlayerName : Player 2 Score : 978,632 Timestamp : 2016-05-02
PlayerId : 1358098565 PlayerName : Player 65 Score : 973,257 Timestamp : 2016-10-30
Sekarang mari kita jalankan perintah query
dengan argumen yang diperlukan untuk membuat kueri pemain "Sepuluh Teratas" tahun ini dengan menentukan "timespan" yang sama dengan jumlah jam dalam setahun, yakni 8.760. Pastikan Anda mengganti PROJECT_ID
dengan Project ID yang Anda buat di awal codelab ini.
dotnet run query PROJECT_ID cloudspanner-leaderboard leaderboard 8760
Anda akan melihat respons yang menyertakan pemain "Sepuluh Teratas" tahun ini seperti berikut:
PlayerId : 541473117 PlayerName : Player 22 Score : 991,368 Timestamp : 2018-04-30
PlayerId : 228469898 PlayerName : Player 82 Score : 967,177 Timestamp : 2018-01-26
PlayerId : 1131343000 PlayerName : Player 26 Score : 944,725 Timestamp : 2017-05-26
PlayerId : 396780730 PlayerName : Player 41 Score : 929,455 Timestamp : 2017-09-26
PlayerId : 61891198 PlayerName : Player 19 Score : 921,251 Timestamp : 2018-05-01
PlayerId : 634269851 PlayerName : Player 54 Score : 909,379 Timestamp : 2017-07-24
PlayerId : 821111159 PlayerName : Player 55 Score : 908,402 Timestamp : 2017-05-25
PlayerId : 228469898 PlayerName : Player 82 Score : 889,040 Timestamp : 2017-12-26
PlayerId : 1408782275 PlayerName : Player 27 Score : 874,124 Timestamp : 2017-09-24
PlayerId : 1002199735 PlayerName : Player 35 Score : 864,758 Timestamp : 2018-04-24
Sekarang, mari kita jalankan perintah query
untuk membuat kueri pemain "Sepuluh Teratas" bulan ini dengan menentukan "timespan" yang sama dengan jumlah jam dalam sebulan, yaitu 730. Pastikan Anda mengganti PROJECT_ID
dengan Project ID yang Anda buat di awal codelab ini.
dotnet run query PROJECT_ID cloudspanner-leaderboard leaderboard 730
Anda akan melihat respons yang menyertakan pemain "Sepuluh Teratas" bulan ini seperti berikut:
PlayerId : 541473117 PlayerName : Player 22 Score : 991,368 Timestamp : 2018-04-30
PlayerId : 61891198 PlayerName : Player 19 Score : 921,251 Timestamp : 2018-05-01
PlayerId : 1002199735 PlayerName : Player 35 Score : 864,758 Timestamp : 2018-04-24
PlayerId : 1228490432 PlayerName : Player 11 Score : 682,033 Timestamp : 2018-04-26
PlayerId : 648239230 PlayerName : Player 92 Score : 653,895 Timestamp : 2018-05-02
PlayerId : 70762849 PlayerName : Player 77 Score : 598,074 Timestamp : 2018-04-22
PlayerId : 1671215342 PlayerName : Player 62 Score : 506,770 Timestamp : 2018-04-28
PlayerId : 1208850523 PlayerName : Player 21 Score : 216,008 Timestamp : 2018-04-30
PlayerId : 1587692674 PlayerName : Player 63 Score : 188,157 Timestamp : 2018-04-25
PlayerId : 992391797 PlayerName : Player 37 Score : 167,175 Timestamp : 2018-04-30
Sekarang mari kita jalankan perintah query
untuk membuat kueri pemain "Sepuluh Teratas" minggu ini dengan menetapkan "timespan" yang sama dengan jumlah jam dalam seminggu, yaitu 168. Pastikan Anda mengganti PROJECT_ID
dengan Project ID yang Anda buat di awal codelab ini.
dotnet run query PROJECT_ID cloudspanner-leaderboard leaderboard 168
Anda akan melihat respons yang menyertakan pemain "Sepuluh Teratas" minggu ini seperti berikut:
PlayerId : 541473117 PlayerName : Player 22 Score : 991,368 Timestamp : 2018-04-30
PlayerId : 61891198 PlayerName : Player 19 Score : 921,251 Timestamp : 2018-05-01
PlayerId : 228469898 PlayerName : Player 82 Score : 853,602 Timestamp : 2018-04-28
PlayerId : 1131343000 PlayerName : Player 26 Score : 695,318 Timestamp : 2018-04-30
PlayerId : 1228490432 PlayerName : Player 11 Score : 682,033 Timestamp : 2018-04-26
PlayerId : 1408782275 PlayerName : Player 27 Score : 671,827 Timestamp : 2018-04-27
PlayerId : 648239230 PlayerName : Player 92 Score : 653,895 Timestamp : 2018-05-02
PlayerId : 816861444 PlayerName : Player 83 Score : 622,277 Timestamp : 2018-04-27
PlayerId : 162043954 PlayerName : Player 75 Score : 572,634 Timestamp : 2018-05-02
PlayerId : 1671215342 PlayerName : Player 62 Score : 506,770 Timestamp : 2018-04-28
Bagus!
Sekarang setelah Anda menambahkan data, Spanner akan menskalakan database Anda sesuai kebutuhan.
Tidak peduli seberapa banyak database Anda berkembang, papan peringkat game Anda dapat terus diskalakan secara akurat dengan Spanner dan teknologi Truetime-nya.
7. Pembersihan
Setelah asyik bermain dengan Spanner, kita perlu membersihkan tempat bermain kita, menghemat resource dan uang yang berharga. Untungnya ini adalah langkah yang mudah. Cukup buka Konsol Play dan hapus instance yang kita buat di langkah codelab bernama "Menyiapkan Instance Cloud Spanner".
8. Selamat!
Yang telah kita bahas:
- Instance, Database, dan Skema Tabel Google Cloud Spanner untuk papan peringkat
- Cara membuat aplikasi konsol .NET Core C#
- Cara membuat Database Spanner dan Tabel menggunakan library klien C#
- Cara memuat data ke dalam Database Spanner menggunakan library klien C#
- Cara membuat kueri "Sepuluh Teratas" hasil dari data Anda menggunakan stempel waktu commit Spanner dan library klien C#
Langkah Berikutnya:
- Baca Laporan resmi Spanner CAP
- Pelajari tentang Desain Skema dan Praktik terbaik kueri
- Pelajari lebih lanjut stempel waktu commit Cloud Spanner
Kirimkan masukan Anda
- Luangkan waktu Anda untuk menyelesaikan survei singkat kami