1. Übersicht
Google Cloud Spanner ist ein vollständig verwalteter, horizontal skalierbarer, global verteilter relationaler Datenbankdienst, der ACID-Transaktionen und SQL-Semantik bietet, ohne auf Leistung und Hochverfügbarkeit zu verzichten.
In diesem Lab erfahren Sie, wie Sie eine Cloud Spanner-Instanz einrichten. Sie führen die Schritte zum Erstellen einer Datenbank und eines Schemas aus, die für eine Gaming-Bestenliste verwendet werden können. Zuerst erstellen Sie eine Spielertabelle zur Speicherung von Spielerinformationen und eine Punktzahltabelle, in der die Punktzahlen der Spieler gespeichert werden.
Als Nächstes füllen Sie die Tabellen mit Beispieldaten. Am Ende des Labs führen Sie einige Top-10-Beispielabfragen aus und löschen schließlich die Instanz, um Ressourcen freizugeben.
Aufgaben in diesem Lab
- Cloud Spanner-Instanz einrichten
- Datenbank und Tabellen erstellen
- So verwenden Sie eine Commit-Zeitstempelspalte.
- Daten in eine Cloud Spanner-Datenbanktabelle mit Zeitstempeln laden.
- Anleitung zum Abfragen Ihrer Cloud Spanner-Datenbank.
- Cloud Spanner-Instanz löschen
Voraussetzungen
Wie möchten Sie diese Anleitung nutzen?
<ph type="x-smartling-placeholder">Wie würden Sie Ihre Erfahrung mit der Google Cloud Platform bewerten?
<ph type="x-smartling-placeholder">2. Einrichtung und Anforderungen
Umgebung für das selbstbestimmte Lernen einrichten
Wenn Sie noch kein Google-Konto (Gmail oder Google Apps) haben, müssen Sie eines erstellen. Melden Sie sich in der Google Cloud Platform Console ( console.cloud.google.com) an und erstellen Sie ein neues Projekt.
Wenn Sie bereits ein Projekt haben, klicken Sie auf das Drop-down-Menü für die Projektauswahl oben links in der Konsole:
und klicken Sie auf „NEUES PROJEKT“, Schaltfläche zum Erstellen eines neuen Projekts:
Wenn Sie noch kein Projekt haben, sollten Sie ein Dialogfeld wie dieses sehen, um Ihr erstes zu erstellen:
Im nachfolgenden Dialog zur Projekterstellung können Sie die Details Ihres neuen Projekts eingeben:
Denken Sie an die Projekt-ID. Dies ist ein eindeutiger Name für alle Google Cloud-Projekte. Der oben angegebene Name ist bereits vergeben und funktioniert leider nicht für Sie. Sie wird in diesem Codelab später als PROJECT_ID
bezeichnet.
Falls noch nicht geschehen, müssen Sie als Nächstes in der Developers Console die Abrechnung aktivieren, um Google Cloud-Ressourcen nutzen und die Cloud Spanner API aktivieren zu können.
Dieses Codelab sollte nicht mehr als ein paar Euro kosten. Wenn Sie sich jedoch dazu entschließen, mehr Ressourcen zu verwenden oder diese weiter auszuführen (siehe Abschnitt „Bereinigen“ am Ende dieses Dokuments), Die Preise für Google Cloud Spanner finden Sie hier.
Neue Google Cloud Platform-Nutzer haben Anspruch auf eine kostenlose Testversion mit 300$Guthaben, wodurch das Codelab in der Regel kostenlos sein sollte.
Google Cloud Shell einrichten
Sie können Google Cloud und Spanner per Fernzugriff von Ihrem Laptop aus bedienen. In diesem Codelab verwenden wir jedoch Google Cloud Shell, eine Befehlszeilenumgebung, die in der Cloud ausgeführt wird.
Diese Debian-basierte virtuelle Maschine verfügt über alle erforderlichen Entwicklungstools. Es bietet ein Basisverzeichnis mit 5 GB nichtflüchtigem Speicher und wird in Google Cloud ausgeführt. Dadurch werden die Netzwerkleistung und die Authentifizierung erheblich verbessert. Für dieses Codelab benötigen Sie also nur einen Browser – ja, er funktioniert auf Chromebooks.
- Klicken Sie einfach auf Cloud Shell aktivieren , um Cloud Shell über die Cloud Console zu aktivieren. Die Bereitstellung und Verbindung mit der Umgebung dauert einen Moment.
Sobald Sie mit Cloud Shell verbunden sind, sollten Sie sehen, dass Sie bereits authentifiziert sind und dass das Projekt bereits auf Ihre PROJECT_ID
eingestellt ist.
gcloud auth list
Befehlsausgabe
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
Befehlsausgabe
[core] project = <PROJECT_ID>
Sollte das Projekt aus irgendeinem Grund nicht eingerichtet sein, geben Sie einfach den folgenden Befehl ein:
gcloud config set project <PROJECT_ID>
Du suchst dein Gerät (PROJECT_ID
)? Sehen Sie nach, welche ID Sie bei den Einrichtungsschritten verwendet haben, oder rufen Sie sie im Dashboard der Cloud Console auf:
Cloud Shell legt außerdem standardmäßig einige Umgebungsvariablen fest, die bei der Ausführung zukünftiger Befehle nützlich sein können.
echo $GOOGLE_CLOUD_PROJECT
Befehlsausgabe
<PROJECT_ID>
- Legen Sie schließlich die Standardzone und die Projektkonfiguration fest.
gcloud config set compute/zone us-central1-f
Sie können verschiedene Zonen auswählen. Weitere Informationen finden Sie unter Regionen und Zonen.
Zusammenfassung
In diesem Schritt richten Sie Ihre Umgebung ein.
Nächstes Thema
Als Nächstes richten Sie eine Cloud Spanner-Instanz ein.
3. Cloud Spanner-Instanz einrichten
In diesem Schritt richten wir unsere Cloud Spanner-Instanz für dieses Codelab ein. Suchen Sie im linken Hamburger-Menü nach dem Spanner-Eintrag oder drücken Sie „/“, um nach Spanner zu suchen und geben Sie „Spanner“ ein
Klicken Sie als Nächstes auf und füllen Sie das Formular aus. Geben Sie dazu den Instanznamen cloudspanner-leaderboard für Ihre Instanz ein, wählen Sie eine Konfiguration aus (wählen Sie eine regionale Instanz aus) und legen Sie die Anzahl der Knoten fest. Für dieses Codelab benötigen wir nur einen Knoten. Für Produktionsinstanzen und zur Einhaltung des Cloud Spanner-SLA müssen Sie mindestens drei Knoten in Ihrer Cloud Spanner-Instanz ausführen.
Klicken Sie abschließend auf „Erstellen“. und innerhalb von Sekunden steht eine Cloud Spanner-Instanz zur Verfügung.
Im nächsten Schritt erstellen wir mithilfe der Java-Clientbibliothek eine Datenbank und ein Schema in der neuen Instanz.
4. Datenbank und Schema erstellen
In diesem Schritt erstellen wir die Beispieldatenbank und das Schema.
Erstellen wir mit der Java-Client-Bibliothek zwei Tabellen. eine Spielertabelle mit Spielerinformationen und eine Punktzahltabelle zum Speichern der Punktzahlen der Spieler Gehen Sie dazu die Schritte zum Erstellen einer Java-Konsolenanwendung in Cloud Shell durch.
Klonen Sie zuerst den Beispielcode für dieses Codelab aus GitHub. Geben Sie dazu den folgenden Befehl in Cloud Shell ein:
git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git
Wechseln Sie dann in das Verzeichnis „applications“ Verzeichnis, in dem Sie Ihre Anwendung erstellen.
cd java-docs-samples/spanner/leaderboard
Der gesamte Code, der für dieses Codelab erforderlich ist, befindet sich im vorhandenen java-docs-samples/spanner/leaderboard/complete
-Verzeichnis als ausführbare C#-Anwendung mit dem Namen Leaderboard
. Sie dient als Referenz, während Sie das Codelab durchlaufen. Wir werden ein neues Verzeichnis erstellen und schrittweise eine Kopie der Leaderboard-Anwendung erstellen.
Erstellen Sie ein neues Verzeichnis mit dem Namen „codelab“. für die Anwendung und wechseln Sie mit dem folgenden Befehl in das entsprechende Verzeichnis:
mkdir codelab && cd $_
Erstellen Sie eine neue, einfache Java-Anwendung namens "Leaderboard". Verwenden Sie dazu den folgenden Maven-Befehl (mvn):
mvn -B archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=com.google.codelabs -DartifactId=leaderboard -DarchetypeVersion=1.4
Mit diesem Befehl wird eine einfache Konsolenanwendung erstellt, die aus zwei primären Dateien besteht: der Maven-App-Konfigurationsdatei pom.xml
und der Java-App-Datei App.java
.
Ändern Sie als Nächstes das Verzeichnis in das soeben erstellte Bestenlistenverzeichnis und listen Sie seinen Inhalt auf:
cd leaderboard && ls
Sie sollten die Datei pom.xml
und das Verzeichnis src
sehen:
pom.xml src
Aktualisieren wir nun diese Konsolenanwendung, indem wir App.java
so bearbeiten, dass mithilfe der Java Spanner-Clientbibliothek eine aus zwei Tabellen bestehende Bestenliste erstellt wird. Spieler und Punktzahlen. Sie können dies direkt im Cloud Shell-Editor tun:
Öffnen Sie den Cloud Shell-Editor, indem Sie auf das unten hervorgehobene Symbol klicken:
Öffnen Sie die Datei pom.xml im Bestenlistenordner. Öffnen Sie die Datei „pom.xml“ im Ordner java-docs-samples\ spanner\leaderboard\codelab\leaderboard
.Diese Datei konfiguriert das Maven-Build-System so, dass die Anwendung einschließlich aller Abhängigkeiten in einer JAR-Datei erstellt wird.
Fügen Sie den folgenden 1 neuen Bereich zur Abhängigkeitsverwaltung direkt unter dem vorhandenen </properties> hinzu. :
<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>
Fügen Sie außerdem eine neue Abhängigkeit in den vorhandenen <dependencies> hinzu. der Anwendung die Cloud Spanner Java-Clientbibliothek hinzufügen.
<dependency>
<!-- Version auto-managed by BOM -->
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-spanner</artifactId>
</dependency>
Ersetzen Sie dann den vorhandenen <build>-Abschnitt der Datei pom.xml
. mit dem folgenden <build> -Abschnitt. Abschnitt:
<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>
Speichern Sie die Änderungen an der Datei pom.xml, indem Sie auf "Speichern" klicken. im Cloud Shell-Editor unter „Datei“ oder indem Sie die "Strg"-Taste und „S“ Tasten zusammen.
Öffnen Sie als Nächstes die Datei App.java
im Cloud Shell-Editor im Ordner src/main/java/com/google/codelabs/
. Ersetzen Sie den vorhandenen Code der Datei durch den Code, der zum Erstellen der Datenbank leaderboard
und der Tabellen Players
und Scores
erforderlich ist. Fügen Sie dazu den folgenden Java-Code in die Datei App.java
ein:
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");
}
}
Klicken Sie auf „Speichern“, um die Änderungen an der Datei App.java
zu speichern im Cloud Shell-Editor unter „Datei“ .
Mit der Datei App.java
im Verzeichnis java-docs-samples/spanner/leaderboard/step4/src
können Sie sich ein Beispiel dafür ansehen, wie Ihre Datei App.java
aussehen sollte, nachdem Sie den Code zum Aktivieren des Befehls create
hinzugefügt haben.
Führen Sie zum Erstellen Ihrer App das mvn-Paket in dem Verzeichnis aus, in dem sich die pom.xml
befindet:
mvn package
Nachdem die Java-JAR-Datei erfolgreich erstellt wurde, führen Sie die resultierende Anwendung in Cloud Shell aus, indem Sie den folgenden Befehl eingeben:
java -jar target/leaderboard.jar
Die Ausgabe sollte etwa so aussehen:
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.
Dieser Antwort können wir entnehmen, dass dies die Anwendung Leaderboard
ist, die derzeit einen möglichen Befehl hat: create
. Die erwarteten Argumente des Befehls create
sind Instanz-ID und Datenbank-ID.
Führen Sie nun den folgenden Befehl aus.
java -jar target/leaderboard.jar create cloudspanner-leaderboard leaderboard
Nach einigen Sekunden sollten Sie eine Antwort wie die folgende sehen:
Created database [projects/your-project/instances/cloudspanner-leaderboard/databases/leaderboard]
Im Bereich „Cloud Spanner“ der Cloud Console sollten Sie im linken Menü Ihre neue Datenbank und Ihre Tabellen sehen.
Im nächsten Schritt aktualisieren wir unsere Anwendung, um einige Daten in Ihre neue Datenbank zu laden.
5. Daten laden
Wir haben jetzt eine Datenbank mit dem Namen leaderboard
, die zwei Tabellen enthält. Players
und Scores
. Verwenden wir nun die Java-Clientbibliothek, um unsere Tabelle Players
mit Spielern und unsere Tabelle Scores
mit zufälligen Punktzahlen für jeden Spieler zu füllen.
Wenn der Cloud Shell-Editor noch nicht geöffnet ist, klicken Sie auf das unten hervorgehobene Symbol:
Bearbeiten Sie als Nächstes die Datei App.java
im Cloud Shell-Editor, um einen insert
-Befehl hinzuzufügen, mit dem 100 Spieler in die Tabelle Players
eingefügt werden können. Sie können damit auch 4 Zufallspunktzahlen für jeden Spieler in der Tabelle Players
in die Tabelle Scores
einfügen.
Aktualisieren Sie zuerst den Abschnitt imports
am Anfang der Anwendungsdatei und ersetzen Sie den vorhandenen Abschnitt. Wenn Sie fertig sind, sollte er so aussehen:
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;
Fügen Sie als Nächstes die folgenden Methoden insert, insertPlayers und insertScores unter der vorhandenen Methode create()
und oberhalb der Methode printUsageAndExit()
hinzu:
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...");
}
}
Damit der insert
-Befehl funktioniert, fügen Sie dem Hauptfenster Ihrer App den folgenden Code hinzu: innerhalb der switch (command)
-Anweisung :
case "insert":
String insertType;
try {
insertType = args[3];
} catch (ArrayIndexOutOfBoundsException exception) {
insertType = "";
}
insert(dbClient, insertType);
break;
Wenn Sie fertig sind, sollte die switch (command)
-Anweisung so aussehen:
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();
}
Der letzte Schritt zum Hinzufügen von „insert“ Ihrer App ist es, Hilfetext für „Einfügen“ an die Methode printUsageAndExit()
übergeben. Fügen Sie der Methode printUsageAndExit()
die folgenden Codezeilen hinzu, um Hilfetext für den Einfügebefehl einzuschließen:
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");
Klicken Sie auf „Speichern“, um die Änderungen an der Datei App.java
zu speichern im Cloud Shell-Editor unter „Datei“ .
Mit der Datei App.java
im Verzeichnis java-docs-samples/spanner/leaderboard/step5/src
können Sie sich ein Beispiel dafür ansehen, wie Ihre Datei App.java
aussehen sollte, nachdem Sie den Code zum Aktivieren des Befehls insert
hinzugefügt haben.
Jetzt erstellen wir die App neu und führen sie aus, um zu prüfen, ob der neue insert
-Befehl in der Liste möglicher Befehle der App enthalten ist.
Führen Sie zum Erstellen Ihrer App mvn package
aus dem Verzeichnis aus, in dem sich Ihre pom.xml-Datei befindet:
mvn package
Nachdem die Java-JAR-Datei erfolgreich erstellt wurde, führen Sie den folgenden Befehl aus:
java -jar target/leaderboard.jar
Der Befehl insert
sollte jetzt in der Standardausgabe der Anwendung enthalten sein:
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.
Der Antwort können Sie entnehmen, dass neben der Instanz-ID und der Datenbank-ID ein weiteres Argument vorhanden ist, das den Wert „players“ haben kann. oder "Punktzahlen".
Jetzt führen wir den Befehl insert
mit denselben Argumentwerten aus, die wir beim Aufrufen des Befehls create
verwendet haben, und fügen „players“ hinzu. als zusätzlichen „Insert“-Typ .
java -jar target/leaderboard.jar insert cloudspanner-leaderboard leaderboard players
Nach einigen Sekunden sollten Sie eine Antwort wie die folgende sehen:
Done inserting player records...
Verwenden wir nun die Java-Clientbibliothek, um unsere Scores
-Tabelle mit vier Zufallspunktzahlen und Zeitstempeln für jeden Spieler in der Players
-Tabelle zu füllen.
Die Spalte Timestamp
der Tabelle „Scores
“ wurde als „Commit-Zeitstempel“ definiert Spalte über die folgende SQL-Anweisung, die ausgeführt wurde, als wir zuvor den Befehl create
ausgeführt haben:
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
Beachten Sie das Attribut OPTIONS(allow_commit_timestamp=true)
. Dadurch wird Timestamp
zu einem „Commit-Zeitstempel“ und kann automatisch mit dem genauen Transaktionszeitstempel für INSERT- und UPDATE-Vorgänge in einer bestimmten Tabellenzeile gefüllt werden.
Sie können auch Ihre eigenen Zeitstempelwerte in einen Commit-Zeitstempel einfügen solange Sie einen Zeitstempel mit einem Wert in der Vergangenheit einfügen. In diesem Codelab machen wir das.
Führen wir nun den Befehl insert
mit denselben Argumentwerten aus, die wir beim Aufrufen des create
-Befehls verwendet haben, wobei wir „scores“ hinzufügen. als zusätzlichen „Insert“-Typ .
java -jar target/leaderboard.jar insert cloudspanner-leaderboard leaderboard scores
Nach einigen Sekunden sollten Sie eine Antwort wie die folgende sehen:
Done inserting score records...
insert
mit dem „type of insert“ ausführen , das als scores
angegeben ist, ruft die Methode insertScores
auf, die die folgenden Code-Snippets verwendet, um einen zufällig generierten Zeitstempel mit einem Datum und einer Uhrzeit einzufügen, die in der Vergangenheit liegen:
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())
Um die Spalte Timestamp
automatisch mit dem Zeitstempel zu füllen, der genau dem Zeitpunkt entspricht, an dem das Transaktion stattfindet, können Sie stattdessen die Java-Konstante Value.COMMIT_TIMESTAMP
wie im folgenden Code-Snippet einfügen:
.bind("Timestamp")
.to(Value.COMMIT_TIMESTAMP)
Nachdem die Daten geladen wurden, überprüfen wir die Werte, die wir gerade in unsere neuen Tabellen geschrieben haben. Wählen Sie zuerst die Datenbank leaderboard
und dann die Tabelle Players
aus. Klicken Sie auf den Tab Data
. Sie sollten sehen, dass sich in den Spalten PlayerId
und PlayerName
der Tabelle Daten befinden.
Prüfen Sie als Nächstes, ob die Tabelle „Scores“ auch Daten enthält. Klicken Sie dazu auf die Tabelle Scores
und wählen Sie den Tab Data
aus. Die Spalten PlayerId
, Timestamp
und Score
der Tabelle sollten Daten enthalten.
Gut gemacht! Wir aktualisieren nun unsere App und führen einige Abfragen aus, mit denen wir eine Gaming-Bestenliste erstellen können.
6. Abfragen zu Bestenlisten ausführen
Nachdem wir unsere Datenbank eingerichtet und Informationen in unsere Tabellen geladen haben, erstellen wir nun mit diesen Daten eine Bestenliste. Dazu müssen wir die folgenden vier Fragen beantworten:
- Welche Spieler sind die "Top Ten"? aller Zeiten?
- Welche Spieler sind die "Top Ten"? des Jahres?
- Welche Spieler sind die "Top Ten"? des Monats?
- Welche Spieler sind die "Top Ten"? der Woche?
Wir aktualisieren nun unsere App, um die SQL-Abfragen auszuführen, die diese Fragen beantworten.
Wir fügen einen query
-Befehl hinzu, der eine Möglichkeit bietet, die Abfragen auszuführen, um die Fragen zu beantworten, die die für unsere Bestenliste erforderlichen Informationen liefern.
Bearbeiten Sie die Datei App.java
im Cloud Shell-Editor, um der Anwendung einen query
-Befehl hinzuzufügen. Der Befehl query
besteht aus zwei query
-Methoden. Die eine verwendet nur ein DatabaseClient
-Argument und die andere mit einem zusätzlichen timespan
-Argument, um das Filtern der Ergebnisse nach einem in Stunden angegebenen Zeitraum zu erleichtern.
Fügen Sie die folgenden beiden query
-Methoden unter der vorhandenen Methode insertScores()
und über der vorhandenen Methode printUsageAndExit()
hinzu:
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));
}
}
Damit der query
-Befehl funktioniert, fügen Sie der switch(command)
-Anweisung im Hauptbereich Ihrer App den folgenden Code hinzu: :
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;
Der letzte Schritt zum Hinzufügen von „query“ Ihrer App besteht darin, Hilfetext für die „Suchanfrage“ an die Methode printUsageAndExit()
übergeben. Fügen Sie der Methode printUsageAndExit()
die folgenden Codezeilen hinzu, um Hilfetext für die Abfrage einzubinden Befehl:
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");
Klicken Sie auf „Speichern“, um die Änderungen an der Datei App.java
zu speichern im Cloud Shell-Editor unter „Datei“ .
Mit der Datei App.java
im Verzeichnis dotnet-docs-samples/applications/leaderboard/step6/src
können Sie sich ein Beispiel dafür ansehen, wie Ihre Datei App.java
aussehen sollte, nachdem Sie den Code zum Aktivieren des Befehls query
hinzugefügt haben.
Führen Sie zum Erstellen Ihrer App mvn package
aus dem Verzeichnis aus, in dem sich Ihre pom.xml-Datei befindet:
mvn package
Führen Sie nun die App aus, um zu prüfen, ob der neue query
-Befehl in der Liste möglicher Befehle der App enthalten ist. Führen Sie dazu diesen Befehl aus:
java -jar target/leaderboard.jar
Der Befehl query
sollte jetzt in der Standardausgabe der App als neue Befehlsoption enthalten sein:
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.
Wie Sie der Antwort entnehmen können, können wir mit dem Befehl query
zusätzlich zu den Argumenten für Instanz-ID und Datenbank-ID eine optionale Zeitspanne in Stunden angeben, die zum Filtern von Datensätzen basierend auf ihrem Wert in der Spalte Timestamp
der Tabelle Scores
verwendet wird. Da das Zeitspannenargument optional ist, werden keine Datensätze nach Zeitstempeln gefiltert, wenn kein entsprechendes Argument enthalten ist. Wir können also den Befehl query
ohne „timespan“ verwenden. um eine Liste der Top Ten zu erhalten, aller Zeiten.
Lassen Sie uns den Befehl query
ohne Angabe einer Zeitspanne ausführen. Verwenden Sie dabei dieselben Argumentwerte, die wir bei der Ausführung des Befehls create
verwendet haben.
java -jar target/leaderboard.jar query cloudspanner-leaderboard leaderboard
Sie sollten nun eine Antwort sehen, die die Top Ten enthält. wie die folgenden:
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
Führen wir nun den Befehl query
mit den erforderlichen Argumenten aus, um die Top Ten abzufragen. Spieler des Jahres durch Angabe einer „Zeitspanne“ entspricht der Anzahl der Stunden in einem Jahr, also 8.760.
java -jar target/leaderboard.jar query cloudspanner-leaderboard leaderboard 8760
Sie sollten nun eine Antwort sehen, die die Top Ten enthält. Spieler des Jahres:
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
Führen wir nun den Befehl query
aus, um die Top Ten abzufragen. Spieler des Monats durch Angabe einer Zeitspanne der Anzahl der Stunden pro Monat,
also 730.
java -jar target/leaderboard.jar query cloudspanner-leaderboard leaderboard 730
Sie sollten nun eine Antwort sehen, die die Top Ten enthält. Spieler des Monats:
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
Führen wir nun den Befehl query
aus, um die Top Ten abzufragen. der Woche durch Angabe einer
„Zeitraum“-Zeitspanne der Anzahl der Stunden pro Woche (168).
java -jar target/leaderboard.jar query cloudspanner-leaderboard leaderboard 168
Sie sollten nun eine Antwort sehen, die die Top Ten enthält. der Woche:
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
Super!
Wenn Sie jetzt Einträge hinzufügen, skaliert Cloud Spanner Ihre Datenbank auf eine beliebige Größe. Ganz gleich, wie stark Ihre Datenbank wächst – die Bestenliste Ihres Spiels kann mit Cloud Spanner und seiner Truetime-Technologie weiterhin präzise skaliert werden.
7. Bereinigen
Nach so viel Spaß beim Spielen mit Spanner müssen wir unseren Spielplatz aufräumen und dabei kostbare Ressourcen und Geld sparen. Dies ist jedoch ein einfacher Schritt. Rufen Sie einfach den Cloud Spanner-Bereich der Cloud Console auf und löschen Sie die Instanz, die Sie im Codelab-Schritt "Setup a Cloud Spanner Instance" (Cloud Spanner-Instanz einrichten) erstellt haben.
8. Glückwunsch!
Behandelte Themen:
- Google Cloud Spanner-Instanzen, -Datenbanken und -Tabellenschema für eine Bestenliste
- Java-Konsolenanwendung erstellen
- Spanner-Datenbank und -Tabellen mit der Java-Clientbibliothek erstellen
- Daten mithilfe der Java-Clientbibliothek in eine Spanner-Datenbank laden
- Abfrage der „Top Ten“ Ergebnisse aus Ihren Daten mithilfe von Spanner-Commit-Zeitstempeln und der Java-Clientbibliothek
Vorgehensweise:
- Spanner CAP-Whitepaper lesen
- Weitere Informationen zum Schemadesign und zu Best Practices für Abfragen
- Weitere Informationen zu Commit-Zeitstempeln in Cloud Spanner
Feedback geben
- Bitte nehmen Sie sich einen Moment Zeit, um an unserer kurzen Umfrage teilzunehmen.