1. Genel Bakış
Google Cloud Spanner, performanstan ve yüksek kullanılabilirlikten ödün vermeden ACID işlemleri ve SQL semantiği sağlayan, tümüyle yönetilen, yatay olarak ölçeklenebilir, küresel olarak dağıtılmış bir ilişkisel veritabanı hizmetidir.
Bu laboratuvarda, Cloud Spanner örneği oluşturmayı öğreneceksiniz. Oyun skor tablosu için kullanılabilecek bir veritabanı ve şema oluşturma adımlarını inceleyeceksiniz. Oyuncu bilgilerini saklamak için bir Oyuncular tablosu, oyuncu skorlarını saklamak için bir Skor tablosu oluşturarak başlayın.
Ardından tabloları örnek verilerle dolduracaksınız. Ardından, kaynakları boşa çıkarmak için en iyi on örnek sorguyu çalıştırarak ve son olarak da örneği silerek laboratuvarı tamamlayacaksınız.
Neler öğreneceksiniz?
- Cloud Spanner örneği oluşturma.
- Veritabanı ve tablo oluşturma
- Kaydetme zaman damgası sütunu nasıl kullanılır?
- Cloud Spanner veritabanı tablonuza zaman damgalarıyla veri yükleme.
- Cloud Spanner veritabanınızı sorgulama.
- Cloud Spanner örneğinizi silme.
Gerekenler
Bu eğiticiden nasıl yararlanacaksınız?
Google Cloud Platform deneyiminizi nasıl değerlendirirsiniz?
2. Kurulum ve Gereksinimler
Kendi hızınızda ortam kurulumu
Google Hesabınız (Gmail veya Google Apps) yoksa bir hesap oluşturmanız gerekir. Google Cloud Platform konsolunda ( console.cloud.google.com) oturum açın ve yeni bir proje oluşturun.
Zaten bir projeniz varsa konsolun sol üst köşesindeki proje seçimi açılan menüsünü tıklayın:
Sonra ‘YENİ PROJE’yi tıklayın. düğmesini tıklayın:
Henüz projeniz yoksa ilk projenizi oluşturmak için şuna benzer bir iletişim kutusu görmeniz gerekir:
Sonraki proje oluşturma iletişim kutusu yeni projenizin ayrıntılarını girmenize olanak tanır:
Tüm Google Cloud projeleri için benzersiz bir ad olan proje kimliğini unutmayın (yukarıdaki ad daha önce alınmış ve size uygun olmayacaktır!). Bu kod laboratuvarın ilerleyen bölümlerinde PROJECT_ID
olarak adlandırılacaktır.
Ardından, henüz yapmadıysanız Developers Console'da faturalandırmayı etkinleştirmeniz ve Google Cloud kaynaklarını kullanmanız ve Cloud Spanner API'yi etkinleştirmeniz gerekir.
Bu codelab'i çalıştırmanın maliyeti birkaç dolardan fazla değildir. Ancak daha fazla kaynak kullanmaya karar verirseniz veya bu kaynakları çalışır durumda bırakırsanız daha yüksek ücret ödemeniz gerekebilir (bu belgenin sonundaki "temizlik" bölümüne bakın). Google Cloud Spanner fiyatlandırması burada açıklanmıştır.
Yeni Google Cloud Platform kullanıcıları, bu codelab'i tamamen ücretsiz hale getirecek 300 ABD doları değerindeki ücretsiz denemeden yararlanabilir.
Google Cloud Shell Kurulumu
Google Cloud ve Spanner, dizüstü bilgisayarınızdan uzaktan çalıştırılabilse de bu codelab'de, Cloud'da çalışan bir komut satırı ortamı olan Google Cloud Shell'i kullanacağız.
Bu Debian tabanlı sanal makine, ihtiyacınız olan tüm geliştirme araçlarıyla yüklüdür. 5 GB boyutunda kalıcı bir ana dizin sunar ve Google Cloud'da çalışarak ağ performansını ve kimlik doğrulamasını büyük ölçüde iyileştirir. Yani bu codelab'de ihtiyacınız olan tek şey bir tarayıcıdır (Evet, Chromebook'ta çalışır).
- Cloud Shell'i Cloud Console'dan etkinleştirmek için Cloud Shell'i etkinleştir simgesini tıklamanız yeterlidir (sağlanması ve ortama bağlanması yalnızca birkaç dakika sürer).
Cloud Shell'e bağlandıktan sonra kimliğinizin doğrulandığını ve projenin PROJECT_ID
olarak ayarlanmış olduğunu göreceksiniz.
gcloud auth list
Komut çıkışı
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
Komut çıkışı
[core] project = <PROJECT_ID>
Herhangi bir nedenle proje ayarlanmamışsa şu komutu vermeniz yeterlidir:
gcloud config set project <PROJECT_ID>
PROJECT_ID
cihazınızı mı arıyorsunuz? Kurulum adımlarında kullandığınız kimliği kontrol edin veya Cloud Console kontrol panelinden arayın:
Cloud Shell bazı ortam değişkenlerini de varsayılan olarak ayarlar. Bu değişkenler, gelecekte komut çalıştırdığınızda işinize yarayabilir.
echo $GOOGLE_CLOUD_PROJECT
Komut çıkışı
<PROJECT_ID>
- Son olarak, varsayılan alt bölgeyi ve proje yapılandırmasını ayarlayın.
gcloud config set compute/zone us-central1-f
Çeşitli farklı alt bölgeler seçebilirsiniz. Daha fazla bilgi için Bölgeler ve Bölgeler.
Özet
Bu adımda ortamınızı ayarlarsınız.
Sonraki bölüm
Şimdi bir Cloud Spanner örneği kuracaksınız.
3. Cloud Spanner Örneği Oluşturma
Bu adımda, bu codelab için Cloud Spanner örneğimizi oluşturduk. Soldaki Hamburger Menüsünde Spanner girişini veya "/" tuşuna basarak Spanner girişini arayın ve "Spanner" yazın.
Ardından düğmesini tıklayın ve örneğiniz için cloudspanner-leaderboard örnek adını girip bir yapılandırma seçip (bölgesel bir örnek seçin) ve düğüm sayısını ayarlayın. Bu codelab için yalnızca 1 düğüme ihtiyacımız olacaktır. Üretim örnekleri için ve Cloud Spanner HDS'si (Hizmet Düzeyi Sözleşmesi) şartlarına uygun olmak üzere, Cloud Spanner örneğinizde en az 3 düğüm çalıştırmanız gerekir.
Son olarak, "Oluştur"u tıklayın. ve birkaç saniye içinde Cloud Spanner örneğiniz olur.
Sonraki adımda yeni örneğimizde veritabanı ve şema oluşturmak için Java istemci kitaplığını kullanacağız.
4. Veritabanı ve şema oluşturma
Bu adımda örnek veritabanımızı ve şemamızı oluşturacağız.
Şimdi, Java istemci kitaplığını kullanarak iki tablo oluşturalım: Oyuncu bilgileri için Oyuncular tablosu, oyuncu skorlarını kaydetmek için de Skorlar tablosu. Bunun için Cloud Shell'de Java konsolu uygulaması oluşturma adımlarını inceleyeceğiz.
Öncelikle Cloud Shell'de aşağıdaki komutu yazarak GitHub'dan bu codelab için örnek kodu klonlayın:
git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git
Ardından dizini "applications" (uygulamalar) olarak değiştirin uygulamanızı oluşturacağınız dizindir.
cd java-docs-samples/spanner/leaderboard
Bu codelab'de gerekli olan tüm kodlar, codelab'de ilerlerken referans olarak kullanılmak üzere Leaderboard
adlı çalıştırılabilir bir C# uygulaması olarak mevcut java-docs-samples/spanner/leaderboard/complete
dizininde bulunmaktadır. Yeni bir dizin oluşturup Skor Tablosu uygulamasının bir kopyasını aşamalı olarak hazırlayacağız.
"codelab" adlı yeni bir dizin oluşturun dokunun ve aşağıdaki komutla dizini değiştirin:
mkdir codelab && cd $_
"Leaderboard" adlı yeni bir temel Java uygulaması oluşturun kullanarak aşağıdaki Maven (mvn) komutunu kullanabilirsiniz:
mvn -B archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=com.google.codelabs -DartifactId=leaderboard -DarchetypeVersion=1.4
Bu komut, iki birincil dosya (Maven uygulamasının yapılandırma dosyası pom.xml
ve Java uygulaması App.java
) dosyadan oluşan basit bir konsol uygulaması oluşturur.
Daha sonra, dizini yeni oluşturulan leaderboard diziniyle değiştirin ve içeriğini listeleyin:
cd leaderboard && ls
Listede pom.xml
dosyası ve src
dizini gösterilir:
pom.xml src
Şimdi App.java
öğesini düzenleyerek iki tablodan oluşan bir leaderboard oluşturmak için Java Spanner istemci kitaplığını kullanarak bu konsol uygulamasını güncelleyelim; Oyuncular ve Skorlar. Bu işlemi doğrudan Cloud Shell Düzenleyici'de yapabilirsiniz:
Aşağıda vurgulanan simgeyi tıklayarak Cloud Shell Düzenleyici'yi açın:
Leaderboard klasörünün altındaki pom.xml dosyasını açın. java-docs-samples\ spanner\leaderboard\codelab\leaderboard
klasöründeki pom.xml dosyasını açın.Bu dosya, maven derleme sistemini, uygulamamızı tüm bağımlılıklarımızı içerecek şekilde bir jar içinde derleyecek şekilde yapılandırır.
Aşağıdaki 1 yeni bağımlılık yönetimi bölümünü mevcut </properties> bölümünün hemen altına ekleyin öğe:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-bom</artifactId>
<version>0.83.0-alpha</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Ayrıca mevcut <dependencies> içine 1 yeni bağımlılık ekleyin. bölümüne göz atacağız. Bu bölüm, Cloud Spanner Java istemci kitaplığını uygulamaya ekleyecek.
<dependency>
<!-- Version auto-managed by BOM -->
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-spanner</artifactId>
</dependency>
Sonra pom.xml
dosyasının mevcut <build> öğesini değiştirin bölümünü bölüm:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.5</version>
<configuration>
<finalName>leaderboard</finalName>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.google.codelabs.App</mainClass>
</manifest>
</archive>
<appendAssemblyId>false</appendAssemblyId>
<attach>false</attach>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.0.0-M3</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<useSystemClassLoader>false</useSystemClassLoader>
</configuration>
</plugin>
</plugins>
</build>
pom.xml dosyasında yaptığınız değişiklikleri "Kaydet"i seçerek kaydedin. Cloud Shell Düzenleyici'nin "Dosya" bölümünde tuşuna basarak veya "Ctrl" tuşuna basarak ve "S" klavye tuşlarını basılı tutun.
Ardından, src/main/java/com/google/codelabs/
klasöründe bulunan Cloud Shell Düzenleyici'de App.java
dosyasını açın. Aşağıdaki Java kodunu App.java
dosyasına yapıştırarak leaderboard
veritabanını ve Players
ile Scores
tablolarını oluşturmak için gerekli olan kodla dosyanın mevcut kodunu değiştirin:
package com.google.codelabs;
import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.spanner.Database;
import com.google.cloud.spanner.DatabaseAdminClient;
import com.google.cloud.spanner.DatabaseClient;
import com.google.cloud.spanner.DatabaseId;
import com.google.cloud.spanner.Spanner;
import com.google.cloud.spanner.SpannerException;
import com.google.cloud.spanner.SpannerExceptionFactory;
import com.google.cloud.spanner.SpannerOptions;
import com.google.spanner.admin.database.v1.CreateDatabaseMetadata;
import java.util.Arrays;
import java.util.concurrent.ExecutionException;
/**
* Example code for using the Cloud Spanner API with the Google Cloud Java client library
* to create a simple leaderboard.
*
* This example demonstrates:
*
* <p>
*
* <ul>
* <li>Creating a Cloud Spanner database.
* </ul>
*/
public class App {
static void create(DatabaseAdminClient dbAdminClient, DatabaseId db) {
OperationFuture<Database, CreateDatabaseMetadata> op =
dbAdminClient.createDatabase(
db.getInstanceId().getInstance(),
db.getDatabase(),
Arrays.asList(
"CREATE TABLE Players(\n"
+ " PlayerId INT64 NOT NULL,\n"
+ " PlayerName STRING(2048) NOT NULL\n"
+ ") PRIMARY KEY(PlayerId)",
"CREATE TABLE Scores(\n"
+ " PlayerId INT64 NOT NULL,\n"
+ " Score INT64 NOT NULL,\n"
+ " Timestamp TIMESTAMP NOT NULL\n"
+ " OPTIONS(allow_commit_timestamp=true)\n"
+ ") PRIMARY KEY(PlayerId, Timestamp),\n"
+ "INTERLEAVE IN PARENT Players ON DELETE NO ACTION"));
try {
// Initiate the request which returns an OperationFuture.
Database dbOperation = op.get();
System.out.println("Created database [" + dbOperation.getId() + "]");
} catch (ExecutionException e) {
// If the operation failed during execution, expose the cause.
throw (SpannerException) e.getCause();
} catch (InterruptedException e) {
// Throw when a thread is waiting, sleeping, or otherwise occupied,
// and the thread is interrupted, either before or during the activity.
throw SpannerExceptionFactory.propagateInterrupt(e);
}
}
static void printUsageAndExit() {
System.out.println("Leaderboard 1.0.0");
System.out.println("Usage:");
System.out.println(" java -jar leaderboard.jar "
+ "<command> <instance_id> <database_id> [command_option]");
System.out.println("");
System.out.println("Examples:");
System.out.println(" java -jar leaderboard.jar create my-instance example-db");
System.out.println(" - Create a sample Cloud Spanner database along with "
+ "sample tables in your project.\n");
System.exit(1);
}
public static void main(String[] args) throws Exception {
if (!(args.length == 3 || args.length == 4)) {
printUsageAndExit();
}
SpannerOptions options = SpannerOptions.newBuilder().build();
Spanner spanner = options.getService();
try {
String command = args[0];
DatabaseId db = DatabaseId.of(options.getProjectId(), args[1], args[2]);
DatabaseClient dbClient = spanner.getDatabaseClient(db);
DatabaseAdminClient dbAdminClient = spanner.getDatabaseAdminClient();
switch (command) {
case "create":
create(dbAdminClient, db);
break;
default:
printUsageAndExit();
}
} finally {
spanner.close();
}
System.out.println("Closed client");
}
}
App.java
dosyasında yaptığınız değişiklikleri "Kaydet"i seçerek kaydedin. Cloud Shell Düzenleyici'nin "Dosya" bölümünde tıklayın.
create
komutunu etkinleştirme kodu eklendikten sonra App.java
dosyanızın nasıl görünmesi gerektiğine dair bir örnek görmek için java-docs-samples/spanner/leaderboard/step4/src
dizinindeki App.java
dosyasını kullanabilirsiniz.
Uygulamanızı derlemek için pom.xml
uygulamanızın bulunduğu dizinden mvn paketini çalıştırın:
mvn package
Java jar dosyanız başarıyla oluşturulduktan sonra, aşağıdaki komutu girerek gösterilen uygulamayı Cloud Shell'de çalıştırın:
java -jar target/leaderboard.jar
Şuna benzer bir çıkış alırsınız:
Leaderboard 1.0.0 Usage: java -jar leaderboard.jar <command> <instance_id> <database_id> [command_option] Examples: java -jar leaderboard.jar create my-instance example-db - Create a sample Cloud Spanner database along with sample tables in your project.
Bu yanıttan, şu anda olası bir komuta sahip olan Leaderboard
uygulamasının bu olduğunu görüyoruz: create
. create
komutunun beklenen bağımsız değişkenlerinin Örnek Kimliği ve Veritabanı Kimliği olduğunu görebiliyoruz.
Şimdi aşağıdaki komutu çalıştırın.
java -jar target/leaderboard.jar create cloudspanner-leaderboard leaderboard
Birkaç saniye sonra, aşağıdaki gibi bir yanıt görürsünüz:
Created database [projects/your-project/instances/cloudspanner-leaderboard/databases/leaderboard]
Cloud Console'un Cloud Spanner bölümünde, soldaki menüde yeni veritabanınızı ve tablolarınızı göreceksiniz.
Sonraki adımda, yeni veritabanınıza bazı veriler yüklemek için uygulamamızı güncelleyeceğiz.
5. Verileri Yükle
Artık leaderboard
adında iki tablo içeren bir veritabanımız var; Players
ve Scores
. Şimdi Players
tablomuzu oyuncularla, Scores
tablomuzu da her oyuncu için rastgele skorlarla doldurmak için Java istemci kitaplığını kullanalım.
Açık değilse Cloud Shell Düzenleyici'yi aşağıda vurgulanan simgeyi tıklayarak açın:
Ardından, Players
tablosuna 100 oyuncu eklemek üzere veya Players
tablosundaki her oyuncu için Scores
tablosuna 4 rastgele puan eklemek üzere kullanılabilecek bir insert
komutu eklemek için Cloud Shell Düzenleyici'de App.java
dosyasını düzenleyin.
Öncelikle uygulama dosyasının üst kısmındaki imports
bölümünü güncelleyin. Mevcut bölümü, işiniz bittiğinde aşağıdaki gibi görünecek şekilde değiştirin:
package com.google.codelabs;
import static com.google.cloud.spanner.TransactionRunner.TransactionCallable;
import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.spanner.Database;
import com.google.cloud.spanner.DatabaseAdminClient;
import com.google.cloud.spanner.DatabaseClient;
import com.google.cloud.spanner.DatabaseId;
import com.google.cloud.spanner.Mutation;
import com.google.cloud.spanner.ResultSet;
import com.google.cloud.spanner.Spanner;
import com.google.cloud.spanner.SpannerException;
import com.google.cloud.spanner.SpannerExceptionFactory;
import com.google.cloud.spanner.SpannerOptions;
import com.google.cloud.spanner.Statement;
import com.google.cloud.spanner.TransactionContext;
import com.google.spanner.admin.database.v1.CreateDatabaseMetadata;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadLocalRandom;
Daha sonra, mevcut create()
yönteminin altına ve mevcut printUsageAndExit()
yönteminin üzerine aşağıdaki Insert, insertPlayers ve insertScores yöntemlerini ekleyin:
static void insert(DatabaseClient dbClient, String insertType) {
try {
insertType = insertType.toLowerCase();
} catch (Exception e) {
// Invalid input received, set insertType to empty string.
insertType = "";
}
if (insertType.equals("players")) {
// Insert players.
insertPlayers(dbClient);
} else if (insertType.equals("scores")) {
// Insert scores.
insertScores(dbClient);
} else {
// Invalid input.
System.out.println("Invalid value for 'type of insert'. "
+ "Specify a valid value: 'players' or 'scores'.");
System.exit(1);
}
}
static void insertPlayers(DatabaseClient dbClient) {
dbClient
.readWriteTransaction()
.run(
new TransactionCallable<Void>() {
@Override
public Void run(TransactionContext transaction) throws Exception {
// Get the number of players.
String sql = "SELECT Count(PlayerId) as PlayerCount FROM Players";
ResultSet resultSet = transaction.executeQuery(Statement.of(sql));
long numberOfPlayers = 0;
if (resultSet.next()) {
numberOfPlayers = resultSet.getLong("PlayerCount");
}
// Insert 100 player records into the Players table.
List<Statement> stmts = new ArrayList<Statement>();
long randomId;
for (int x = 1; x <= 100; x++) {
numberOfPlayers++;
randomId = (long) Math.floor(Math.random() * 9_000_000_000L) + 1_000_000_000L;
Statement statement =
Statement
.newBuilder(
"INSERT INTO Players (PlayerId, PlayerName) "
+ "VALUES (@PlayerId, @PlayerName) ")
.bind("PlayerId")
.to(randomId)
.bind("PlayerName")
.to("Player " + numberOfPlayers)
.build();
stmts.add(statement);
}
transaction.batchUpdate(stmts);
return null;
}
});
System.out.println("Done inserting player records...");
}
static void insertScores(DatabaseClient dbClient) {
boolean playerRecordsFound = false;
ResultSet resultSet =
dbClient
.singleUse()
.executeQuery(Statement.of("SELECT * FROM Players"));
while (resultSet.next()) {
playerRecordsFound = true;
final long playerId = resultSet.getLong("PlayerId");
dbClient
.readWriteTransaction()
.run(
new TransactionCallable<Void>() {
@Override
public Void run(TransactionContext transaction) throws Exception {
// Initialize objects for random Score and random Timestamp.
LocalDate endDate = LocalDate.now();
long end = endDate.toEpochDay();
int startYear = endDate.getYear() - 2;
int startMonth = endDate.getMonthValue();
int startDay = endDate.getDayOfMonth();
LocalDate startDate = LocalDate.of(startYear, startMonth, startDay);
long start = startDate.toEpochDay();
Random r = new Random();
List<Statement> stmts = new ArrayList<Statement>();
// Insert 4 score records into the Scores table
// for each player in the Players table.
for (int x = 1; x <= 4; x++) {
// Generate random score between 1,000,000 and 1,000
long randomScore = r.nextInt(1000000 - 1000) + 1000;
// Get random day within the past two years.
long randomDay = ThreadLocalRandom.current().nextLong(start, end);
LocalDate randomDayDate = LocalDate.ofEpochDay(randomDay);
LocalTime randomTime = LocalTime.of(
r.nextInt(23), r.nextInt(59), r.nextInt(59), r.nextInt(9999));
LocalDateTime randomDate = LocalDateTime.of(randomDayDate, randomTime);
Instant randomInstant = randomDate.toInstant(ZoneOffset.UTC);
Statement statement =
Statement
.newBuilder(
"INSERT INTO Scores (PlayerId, Score, Timestamp) "
+ "VALUES (@PlayerId, @Score, @Timestamp) ")
.bind("PlayerId")
.to(playerId)
.bind("Score")
.to(randomScore)
.bind("Timestamp")
.to(randomInstant.toString())
.build();
stmts.add(statement);
}
transaction.batchUpdate(stmts);
return null;
}
});
}
if (!playerRecordsFound) {
System.out.println("Parameter 'scores' is invalid since "
+ "no player records currently exist. First insert players "
+ "then insert scores.");
System.exit(1);
} else {
System.out.println("Done inserting score records...");
}
}
Ardından, insert
komutunun çalışması için aşağıdaki kodu uygulamanızın "ana" koduna ekleyin yöntemini switch (command)
ifadesinde bulabilirsiniz :
case "insert":
String insertType;
try {
insertType = args[3];
} catch (ArrayIndexOutOfBoundsException exception) {
insertType = "";
}
insert(dbClient, insertType);
break;
İşiniz bittiğinde switch (command)
ifadesi aşağıdaki gibi görünmelidir:
switch (command) {
case "create":
create(dbAdminClient, db);
break;
case "insert":
String insertType;
try {
insertType = args[3];
} catch (ArrayIndexOutOfBoundsException exception) {
insertType = "";
}
insert(dbClient, insertType);
break;
default:
printUsageAndExit();
}
"Ekle" eklemeyi tamamlamak için son adım işlevi, "insert" için yardım metni eklemektir. komutunu printUsageAndExit()
yöntemine ekleyin. Insert komutuna ilişkin yardım metnini dahil etmek için printUsageAndExit()
yöntemine aşağıdaki kod satırlarını ekleyin:
System.out.println(" java -jar leaderboard.jar insert my-instance example-db players");
System.out.println(" - Insert 100 sample Player records into the database.\n");
System.out.println(" java -jar leaderboard.jar insert my-instance example-db scores");
System.out.println(" - Insert sample score data into Scores sample Cloud Spanner "
+ "database table.\n");
App.java
dosyasında yaptığınız değişiklikleri "Kaydet"i seçerek kaydedin. Cloud Shell Düzenleyici'nin "Dosya" bölümünde tıklayın.
insert
komutunu etkinleştirme kodu eklendikten sonra App.java
dosyanızın nasıl görünmesi gerektiğine dair bir örnek görmek için java-docs-samples/spanner/leaderboard/step5/src
dizinindeki App.java
dosyasını kullanabilirsiniz.
Şimdi yeni insert
komutunun, uygulamanın olası komutlar listesine eklendiğini onaylamak için uygulamayı yeniden oluşturup çalıştıralım.
Uygulamanızı derlemek için pom.xml dosyanızın bulunduğu dizinden mvn package
komutunu çalıştırın:
mvn package
Java jar dosyanız başarıyla oluşturulduktan sonra, aşağıdaki komutu çalıştırın:
java -jar target/leaderboard.jar
insert
komutunun artık uygulamanın varsayılan çıkışına dahil olduğunu göreceksiniz:
Leaderboard 1.0.0 Usage: java -jar leaderboard.jar <command> <instance_id> <database_id> [command_option] Examples: java -jar leaderboard.jar create my-instance example-db - Create a sample Cloud Spanner database along with sample tables in your project. java -jar leaderboard.jar insert my-instance example-db players - Insert 100 sample Player records into the database. java -jar leaderboard.jar insert my-instance example-db scores - Insert sample score data into Scores sample Cloud Spanner database table.
Yanıttan, Örnek Kimliği ve Veritabanı Kimliği'ne ek olarak, "oynatıcılar" değerine sahip olabilecek başka bir bağımsız değişkenin daha olduğunu görebilirsiniz. kullanabilirsiniz.
Şimdi insert
komutunu, create
komutunu çağırdığımızda kullandığımız bağımsız değişken değerleriyle çalıştırıp "oynatıcılar" ifadesini ekleyerek çalıştıralım ek "ek türü" olarak bağımsız değişkeninin önüne geçer.
java -jar target/leaderboard.jar insert cloudspanner-leaderboard leaderboard players
Birkaç saniye sonra, aşağıdaki gibi bir yanıt görürsünüz:
Done inserting player records...
Şimdi Scores
tablomuzu Players
tablodaki her oynatıcıya ait zaman damgalarıyla birlikte dört rastgele puanla doldurmak için Java istemci kitaplığını kullanalım.
Scores
tablosunun Timestamp
sütunu, "taahhüt zaman damgası" olarak tanımlandı sütununu kontrol edin: daha önce create
komutunu çalıştırdığımızda yürütülen aşağıdaki SQL deyimi:
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
OPTIONS(allow_commit_timestamp=true)
özelliğine dikkat edin. Bu durumda Timestamp
, "taahhüt zaman damgası" haline gelir. sütununu görüntüler ve belirli bir tablo satırındaki INSERT ve UPDATE işlemleri için tam işlem zaman damgasıyla otomatik olarak doldurulmasını sağlar.
Ayrıca, bir "kaydetme zaman damgası"na kendi zaman damgası değerlerinizi de ekleyebilirsiniz. geçmiş bir değere sahip bir zaman damgası eklemeniz gerekir. Bu codelab'in amacı budur.
Şimdi insert
komutunu, "scores" ekleyerek create
komutunu çağırdığımızda kullandığımız bağımsız değişken değerleriyle çalıştıralım. ek "ek türü" olarak bağımsız değişkeninin önüne geçer.
java -jar target/leaderboard.jar insert cloudspanner-leaderboard leaderboard scores
Birkaç saniye sonra, aşağıdaki gibi bir yanıt görürsünüz:
Done inserting score records...
insert
, "type of insert" (ekleme türü) ile çalıştırılıyor belirtilen scores
yöntemi, rastgele oluşturulmuş bir zaman damgası (tarih/saat geçmişte olmak üzere) eklemek için aşağıdaki kod snippet'lerini kullanan insertScores
yöntemini çağırır:
LocalDate endDate = LocalDate.now();
long end = endDate.toEpochDay();
int startYear = endDate.getYear() - 2;
int startMonth = endDate.getMonthValue();
int startDay = endDate.getDayOfMonth();
LocalDate startDate = LocalDate.of(startYear, startMonth, startDay);
long start = startDate.toEpochDay();
...
long randomDay = ThreadLocalRandom.current().nextLong(start, end);
LocalDate randomDayDate = LocalDate.ofEpochDay(randomDay);
LocalTime randomTime = LocalTime.of(
r.nextInt(23), r.nextInt(59), r.nextInt(59), r.nextInt(9999));
LocalDateTime randomDate = LocalDateTime.of(randomDayDate, randomTime);
Instant randomInstant = randomDate.toInstant(ZoneOffset.UTC);
...
.bind("Timestamp")
.to(randomInstant.toString())
Timestamp
sütununun tam olarak "Insert" öğesinin zaman damgasıyla otomatik olarak doldurulması için işlemi gerçekleşirse bunun yerine Java sabitini Value.COMMIT_TIMESTAMP
ekleyebilirsiniz. Örneğin, aşağıdaki kod snippet'ini kullanabilirsiniz:
.bind("Timestamp")
.to(Value.COMMIT_TIMESTAMP)
Veri yüklemeyi tamamladığımıza göre artık yeni tablolarımıza yazdığımız değerleri doğrulayalım. Öncelikle leaderboard
veritabanını ve ardından Players
tablosunu seçin. Data
sekmesini tıklayın. Tablonun PlayerId
ve PlayerName
sütunlarında veri bulunduğunu göreceksiniz.
Şimdi de Scores
tablosunu tıklayıp Data
sekmesini seçerek Puanlar tablosunun veri içerdiğini doğrulayalım. Tablonun PlayerId
, Timestamp
ve Score
sütunlarında verileriniz olduğunu göreceksiniz.
Tebrikler! Oyun skor tablosu oluşturmak için kullanabileceğimiz bazı sorgular çalıştırmak için uygulamamızı güncelleyelim.
6. Skor tablosu sorgularını çalıştırma
Veritabanımızı kurup bilgileri tablolarımıza yüklediğimize göre şimdi bu verileri kullanarak bir skor tablosu oluşturalım. Bunu yapmak için aşağıdaki dört soruyu cevaplamamız gerekiyor:
- "En İyi On" Oyuncular var mı?
- "En İyi On" Oyuncular ne durumda?
- "En İyi On" Oyuncular hakkında bilgi edindiniz?
- "En İyi On" Oyuncular merak ediyor musunuz?
Şimdi uygulamamızı, bu soruları cevaplayacak SQL sorgularını çalıştıracak şekilde güncelleyelim.
Skor tablosu için gereken bilgileri üretecek soruları yanıtlamak üzere, sorguların çalıştırılmasını sağlayacak bir query
komutu ekleyeceğiz.
Uygulamayı query
komutu ekleyerek güncellemek için Cloud Shell Düzenleyici'de App.java
dosyasını düzenleyin. query
komutu, iki query
yönteminden oluşur. Biri yalnızca bir DatabaseClient
bağımsız değişkeni alır, diğeri ise sonuçların saat cinsinden belirtilen bir zaman aralığına göre filtrelenmesini kolaylaştırmak için ek bir timespan
bağımsız değişkeni alır.
Mevcut insertScores()
yönteminin altında ve mevcut printUsageAndExit()
yönteminin üzerinde aşağıdaki iki query
yöntemini ekleyin:
static void query(DatabaseClient dbClient) {
String scoreDate;
String score;
ResultSet resultSet =
dbClient
.singleUse()
.executeQuery(
Statement.of(
"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"));
while (resultSet.next()) {
scoreDate = String.valueOf(resultSet.getTimestamp("Timestamp"));
score = String.format("%,d", resultSet.getLong("Score"));
System.out.printf(
"PlayerId: %d PlayerName: %s Score: %s Timestamp: %s\n",
resultSet.getLong("PlayerId"), resultSet.getString("PlayerName"), score,
scoreDate.substring(0,10));
}
}
static void query(DatabaseClient dbClient, int timespan) {
String scoreDate;
String score;
Statement statement =
Statement
.newBuilder(
"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 HOUR) "
+ "ORDER BY s.Score DESC LIMIT 10")
.bind("Timespan")
.to(timespan)
.build();
ResultSet resultSet =
dbClient
.singleUse()
.executeQuery(statement);
while (resultSet.next()) {
scoreDate = String.valueOf(resultSet.getTimestamp("Timestamp"));
score = String.format("%,d", resultSet.getLong("Score"));
System.out.printf(
"PlayerId: %d PlayerName: %s Score: %s Timestamp: %s\n",
resultSet.getLong("PlayerId"), resultSet.getString("PlayerName"), score,
scoreDate.substring(0,10));
}
}
Ardından, query
komutunun çalışması için aşağıdaki kodu uygulamanızın "ana" komutundaki switch(command)
ifadesine ekleyin yöntem:
case "query":
if (args.length == 4) {
int timespan = 0;
try {
timespan = Integer.parseInt(args[3]);
} catch (NumberFormatException e) {
System.err.println("query command's 'timespan' parameter must be a valid integer.");
System.exit(1);
}
query(dbClient, timespan);
} else {
query(dbClient);
}
break;
"Sorgu" eklemeyi tamamlamak için son adım işlevi, "sorgu" sorgusu için yardım metni eklemektir. komutunu printUsageAndExit()
yöntemine ekleyin. "Sorgu" için yardım metni dahil etmek üzere printUsageAndExit()
yöntemine aşağıdaki kod satırlarını ekleyin komut:
System.out.println(" java -jar leaderboard.jar query my-instance example-db");
System.out.println(" - Query players with top ten scores of all time.\n");
System.out.println(" java -jar leaderboard.jar query my-instance example-db 168");
System.out.println(" - Query players with top ten scores within a timespan "
+ "specified in hours.\n");
App.java
dosyasında yaptığınız değişiklikleri "Kaydet"i seçerek kaydedin. Cloud Shell Düzenleyici'nin "Dosya" bölümünde tıklayın.
query
komutunu etkinleştirme kodu eklendikten sonra App.java
dosyanızın nasıl görünmesi gerektiğine dair bir örnek görmek için dotnet-docs-samples/applications/leaderboard/step6/src
dizinindeki App.java
dosyasını kullanabilirsiniz.
Uygulamanızı derlemek için pom.xml dosyanızın bulunduğu dizinden mvn package
komutunu çalıştırın:
mvn package
Şimdi yeni query
komutunun, uygulamanın olası komutlar listesine eklendiğini onaylamak için uygulamayı çalıştıralım. Aşağıdaki komutu çalıştırın:
java -jar target/leaderboard.jar
Artık query
komutunun, uygulamanın varsayılan çıkışına yeni bir komut seçeneği olarak dahil edildiğini göreceksiniz:
Leaderboard 1.0.0 Usage: java -jar leaderboard.jar <command> <instance_id> <database_id> [command_option] Examples: java -jar leaderboard.jar create my-instance example-db - Create a sample Cloud Spanner database along with sample tables in your project. java -jar leaderboard.jar insert my-instance example-db players - Insert 100 sample Player records into the database. java -jar leaderboard.jar insert my-instance example-db scores - Insert sample score data into Scores sample Cloud Spanner database table. java -jar leaderboard.jar query my-instance example-db - Query players with top ten scores of all time. java -jar leaderboard.jar query my-instance example-db 168 - Query players with top ten scores within a timespan specified in hours.
Yanıttan, Örnek Kimliği ve Veritabanı Kimliği bağımsız değişkenlerine ek olarak, query
komutunun, Scores
tablosunun Timestamp
sütunundaki değerlerine göre kayıtları filtrelemek için kullanılacak, saat cinsinden isteğe bağlı bir zaman aralığı belirtmemize olanak tanıdığını görebilirsiniz. İsteğe bağlı zaman aralığı bağımsız değişkeni, bir zaman aralığı bağımsız değişkeni dahil edilmediğinde hiçbir kaydın zaman damgalarına göre filtrelenmeyeceği anlamına gelir. Böylece query
komutunu "zaman aralığı" olmadan kullanabiliriz. "En İyi On" listemizi almak için "En İyi On" değerini tüm zamanların en iyi oyuncuları.
query
komutunu, create
komutunu çalıştırdığımızda kullandığımız bağımsız değişken değerlerini kullanarak, bir "zaman aralığı" belirtmeden çalıştıralım.
java -jar target/leaderboard.jar query cloudspanner-leaderboard leaderboard
"İlk On" bilgisini içeren bir yanıt göreceksiniz oyuncuları beğenmişsinizdir:
PlayerId: 4018687297 PlayerName: Player 83 Score: 999,618 Timestamp: 2017-07-01
PlayerId: 4018687297 PlayerName: Player 83 Score: 998,956 Timestamp: 2017-09-02
PlayerId: 4285713246 PlayerName: Player 51 Score: 998,648 Timestamp: 2017-12-01
PlayerId: 5267931774 PlayerName: Player 49 Score: 997,733 Timestamp: 2017-11-09
PlayerId: 1981654448 PlayerName: Player 35 Score: 997,480 Timestamp: 2018-12-06
PlayerId: 4953940705 PlayerName: Player 87 Score: 995,184 Timestamp: 2018-09-14
PlayerId: 2456736905 PlayerName: Player 84 Score: 992,881 Timestamp: 2017-04-14
PlayerId: 8234617611 PlayerName: Player 19 Score: 992,399 Timestamp: 2017-12-27
PlayerId: 1788051688 PlayerName: Player 76 Score: 992,265 Timestamp: 2018-11-22
PlayerId: 7127686505 PlayerName: Player 97 Score: 992,038 Timestamp: 2017-12-02
Şimdi "İlk On"u sorgulamak için gerekli bağımsız değişkenlerle birlikte query
komutunu çalıştıralım. yılın oyuncuları için bir "zaman aralığı" 8.760 olan bir yıldaki saat sayısına eşittir.
java -jar target/leaderboard.jar query cloudspanner-leaderboard leaderboard 8760
"İlk On" bilgisini içeren bir yanıt göreceksiniz en iyi performans gösteren oyuncuları şunlar:
PlayerId: 1981654448 PlayerName: Player 35 Score: 997,480 Timestamp: 2018-12-06
PlayerId: 4953940705 PlayerName: Player 87 Score: 995,184 Timestamp: 2018-09-14
PlayerId: 1788051688 PlayerName: Player 76 Score: 992,265 Timestamp: 2018-11-22
PlayerId: 6862349579 PlayerName: Player 30 Score: 990,877 Timestamp: 2018-09-14
PlayerId: 5529627211 PlayerName: Player 16 Score: 989,142 Timestamp: 2018-03-30
PlayerId: 9743904155 PlayerName: Player 1 Score: 988,765 Timestamp: 2018-05-30
PlayerId: 6809119884 PlayerName: Player 7 Score: 986,673 Timestamp: 2018-05-16
PlayerId: 2132710638 PlayerName: Player 54 Score: 983,108 Timestamp: 2018-09-11
PlayerId: 2320093590 PlayerName: Player 79 Score: 981,373 Timestamp: 2018-05-07
PlayerId: 9554181430 PlayerName: Player 80 Score: 981,087 Timestamp: 2018-06-21
Şimdi "İlk On"u sorgulamak için query
komutunu çalıştıralım bir "zaman aralığı" belirleyerek ayın oyuncuları bir aydaki saat sayısına (730) eşittir.
java -jar target/leaderboard.jar query cloudspanner-leaderboard leaderboard 730
"İlk On" bilgisini içeren bir yanıt göreceksiniz şunlar gibi ayın oyuncuları:
PlayerId: 3869829195 PlayerName: Player 69 Score: 949,686 Timestamp: 2019-02-19
PlayerId: 7448359883 PlayerName: Player 20 Score: 938,998 Timestamp: 2019-02-07
PlayerId: 1981654448 PlayerName: Player 35 Score: 929,003 Timestamp: 2019-02-22
PlayerId: 9336678658 PlayerName: Player 44 Score: 914,106 Timestamp: 2019-01-27
PlayerId: 6968576389 PlayerName: Player 40 Score: 898,041 Timestamp: 2019-02-21
PlayerId: 5529627211 PlayerName: Player 16 Score: 896,433 Timestamp: 2019-01-29
PlayerId: 9395039625 PlayerName: Player 59 Score: 879,495 Timestamp: 2019-02-09
PlayerId: 2094604854 PlayerName: Player 39 Score: 860,434 Timestamp: 2019-02-01
PlayerId: 9395039625 PlayerName: Player 59 Score: 849,955 Timestamp: 2019-02-21
PlayerId: 4285713246 PlayerName: Player 51 Score: 805,654 Timestamp: 2019-02-02
Şimdi "İlk On"u sorgulamak için query
komutunu çalıştıralım "zaman aralığı" belirleyerek haftanın oyuncuları bir haftadaki 168 saat olan saat sayısına eşittir.
java -jar target/leaderboard.jar query cloudspanner-leaderboard leaderboard 168
"İlk On" bilgisini içeren bir yanıt göreceksiniz şunlar gibi haftanın oyuncuları:
PlayerId: 3869829195 PlayerName: Player 69 Score: 949,686 Timestamp: 2019-02-19
PlayerId: 1981654448 PlayerName: Player 35 Score: 929,003 Timestamp: 2019-02-22
PlayerId: 6968576389 PlayerName: Player 40 Score: 898,041 Timestamp: 2019-02-21
PlayerId: 9395039625 PlayerName: Player 59 Score: 849,955 Timestamp: 2019-02-21
PlayerId: 5954045812 PlayerName: Player 8 Score: 795,639 Timestamp: 2019-02-22
PlayerId: 3889939638 PlayerName: Player 71 Score: 775,252 Timestamp: 2019-02-21
PlayerId: 5529627211 PlayerName: Player 16 Score: 604,695 Timestamp: 2019-02-19
PlayerId: 9006728426 PlayerName: Player 3 Score: 457,208 Timestamp: 2019-02-22
PlayerId: 8289497066 PlayerName: Player 58 Score: 227,697 Timestamp: 2019-02-20
PlayerId: 8065482904 PlayerName: Player 99 Score: 198,429 Timestamp: 2019-02-24
Harika!
Artık kayıt ekledikçe Cloud Spanner, veritabanınızı ihtiyacınız ne kadar büyük olacak şekilde ölçeklendirir. Veritabanınız ne kadar büyürse yükselsin, oyununuzun skor tablosu, Cloud Spanner ve Truetime teknolojisiyle doğrulukla ölçeklendirilmeye devam edebilir.
7. Temizleme
Spanner ile oynadığımız eğlencenin ardından, oyun alanını temizleyerek değerli kaynaklardan ve paradan tasarruf etmemiz gerekiyor. Neyse ki bu, kolay bir adımdır. Cloud Console'un Cloud Spanner bölümüne gidip "Cloud Spanner Örneği Oluşturma" adlı codelab adımında oluşturduğumuz örneği silmeniz yeterlidir.
8. Tebrikler!
İşlediğimiz konular:
- Leaderboard için Google Cloud Spanner Örnekleri, Veritabanları ve Tablo Şeması
- Java konsolu uygulaması oluşturma
- Java istemci kitaplığını kullanarak Spanner Veritabanı ve Tabloları oluşturma
- Java istemci kitaplığını kullanarak bir Spanner Veritabanına veri yükleme
- "İlk On"u sorgulama Spanner kaydetme zaman damgalarını ve Java istemci kitaplığını kullanarak verilerinizden sonuçlar
Sonraki Adımlar:
- Spanner CAP Teknik Belgesi'ni okuyun
- Şema Tasarımı ve Sorgu en iyi uygulamaları hakkında bilgi edinin.
- Cloud Spanner kaydetme zaman damgaları hakkında daha fazla bilgi
Geri bildiriminizi paylaşın
- Lütfen çok kısa bir süre ayırarak anketimizi doldurun.