目標
このチュートリアルでは、Java 用の Spanner クライアント ライブラリを使用する以下の手順について説明します。
- Spanner のインスタンスとデータベースを作成します。
- データベースのデータに対し、書き込み、読み取り、SQL クエリの実行を行います。
- データベース スキーマを更新します。
- 読み取り / 書き込みトランザクションを使用してデータを更新します。
- セカンダリ インデックスをデータベースに追加します。
- インデックスを使用して、データの読み込みと SQL クエリの実行を行います。
- 読み取り専用トランザクションを使用してデータを取得します。
費用
このチュートリアルでは、Google Cloudの課金対象コンポーネントである Spanner を使用します。Spanner の使用料金については、料金についてのページをご覧ください。
始める前に
設定で説明されている手順を終わらせておきます。この手順では、デフォルトの Google Cloud プロジェクトの作成と設定、課金の有効化、Cloud Spanner API の有効化、Cloud Spanner API の使用に必要な認証情報を取得するための OAuth 2.0 の設定を行います。
特に、gcloud auth
application-default login を使用したローカル開発環境の認証情報の設定は必ず行ってください。
ローカルの Java 環境を準備する
開発マシンに次のものがまだインストールされていない場合はインストールします。
ローカルマシンにサンプルアプリのリポジトリのクローンを作成します。
git clone https://github.com/googleapis/java-spanner.gitSpanner のサンプルコードが含まれるディレクトリに移動します。
cd java-spanner/samples/snippetsサンプル JAR ファイルを生成します。
mvn clean package
インスタンスを作成する
Spanner を最初に使用する際は、インスタンスを作成する必要があります。インスタンスとは、Spanner データベースによって使用されるリソースの割り当てのことです。インスタンスを作成するときは、インスタンス構成を選択してデータの格納場所を指定し、さらに使用するノード数も選択して、インスタンスの配信リソースおよびストレージ リソースの量を決定します。
次のいずれかの方法で Spanner インスタンスを作成する方法については、インスタンスを作成するをご覧ください。インスタンスに test-instance という名前を付けると、このドキュメントの他のトピックで test-instance という名前のインスタンスを参照できます。
- Google Cloud CLI
- Google Cloud コンソール
- クライアント ライブラリ(C++、C#、Go、Java、Node.js、PHP、Python、Ruby)
サンプル ファイルの確認
サンプル リポジトリには、C# で Java を使用する方法を示すサンプルが含まれています。
データベースを作成する
GoogleSQL
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
createdatabase test-instance example-db
PostgreSQL
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
createpgdatabase test-instance example-db
以下のように表示されます。
Created database [example-db]
GoogleSQL
PostgreSQL
次のステップでは、データベースにデータを書き込みます。
データベース クライアントを作成する
読み取りまたは書き込みを行うには、まずDatabaseClient を作成する必要があります。DatabaseClient はデータベース接続と考えることができます。Spanner とのすべてのやり取りは DatabaseClient を経由する必要があります。通常はアプリケーション開始時に DatabaseClient を作成し、読み取り、書き込み、トランザクションの実行に DatabaseClient を再利用します。
クライアントごとに Spanner のリソースを使用するため、close() を呼び出して不要なクライアントを閉じることをおすすめします。
詳細については、DatabaseClient Javadoc リファレンスをご覧ください。
DML を使用してデータを書き込む
読み取り / 書き込みトランザクションでデータ操作言語(DML)を使用してデータを挿入できます。
executeUpdate() メソッドを使用して DML ステートメントを実行します。
writeusingdml 引数を使用してサンプルを実行します。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
writeusingdml test-instance example-db
以下のように表示されます。
4 records inserted.
ミューテーションを使用してデータを書き込む
ミューテーションを使ってデータを挿入することもできます。
データの書き込みには Mutation オブジェクトを使用します。Mutation オブジェクトは、ミューテーション オペレーションのコンテナです。Mutation は、Spanner データベース内のさまざまな行やテーブルに対して、Spanner によってアトミックに適用される一連のオペレーション(挿入、更新、削除)を表します。
Mutation クラスの newInsertBuilder() メソッドは、テーブルに新しい行を挿入する INSERT ミューテーションを作成します。行がすでに存在する場合、書き込みは失敗します。newInsertOrUpdateBuilder メソッドを使用して INSERT_OR_UPDATE ミューテーションを作成することもできます。行がすでに存在している場合は列値が更新されます。
DatabaseClient クラスの write() メソッドはミューテーションを書き込みます。1 つのバッチ内のすべてのミューテーションはアトミックに適用されます。
次のコードで示すのは、ミューテーションを使用してデータを書き込む方法です。
write 引数を使用してサンプルを実行します。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
write test-instance example-db
コマンドが正常に実行されることを確認します。
SQL を使用してデータをクエリする
Spanner では、データの読み取りのために SQL インターフェースがサポートされています。このインターフェースにアクセスするには、コマンドラインで Google Cloud CLI を使用するか、プログラムで Java 用の Spanner クライアント ライブラリを使用します。
コマンドラインを使用する
Albums テーブルのすべての列から値を読み取るには、次の SQL ステートメントを実行します。
gcloud spanner databases execute-sql example-db --instance=test-instance \
--sql='SELECT SingerId, AlbumId, AlbumTitle FROM Albums'
結果は次のようになります。
SingerId AlbumId AlbumTitle
1 1 Total Junk
1 2 Go, Go, Go
2 1 Green
2 2 Forever Hold Your Peace
2 3 Terrified
Java 用の Spanner クライアント ライブラリを使用する
コマンドラインで SQL ステートメントを実行するだけでなく、Java 用の Spanner クライアント ライブラリを使用して同じ SQL ステートメントをプログラマティックに実行できます。
SQL クエリの実行には次のメソッドとクラスが使用されます。DatabaseClientクラスのsingleUse()メソッド: Spanner テーブルの 1 つ以上の行から 1 つ以上の列の値を読み取ります。singleUse()は、読み取りまたは SQL ステートメントを実行するために使用されるReadContextオブジェクトを返します。ReadContextクラスのexecuteQuery()メソッド: データベースに対してクエリを実行します。Statementクラス: SQL 文字列を作成するときに使用します。ResultSetクラス: SQL ステートメントまたは読み取り呼び出しから返されたデータにアクセスします。
クエリを実行してデータにアクセスする方法は次のとおりです。
query 引数を使用してサンプルを実行します。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
query test-instance example-db
次のような結果が表示されます。
1 1 Total Junk
1 2 Go, Go, Go
2 1 Green
2 2 Forever Hold Your Peace
2 3 Terrified
SQL パラメータを使用してクエリする
頻繁に実行されるクエリがアプリケーションにある場合は、対象のクエリをパラメータ化してパフォーマンスを改善できます。パラメータ クエリをキャッシュに保存して再利用することで、コンパイルのコストを削減できます。詳細については、クエリ パラメータを使用して、頻繁に実行するクエリを高速化するをご覧ください。
ここでは、WHERE 句のパラメータを使用して、LastName の特定の値を含むレコードをクエリします。
GoogleSQL
PostgreSQL
queryWithParameter 引数を使用してサンプルを実行します。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
querywithparameter test-instance example-db
次のような結果が表示されます。
12 Melissa Garcia
読み取り API を使用してデータを読み取る
Spanner は SQL インターフェースだけでなく、読み取りインターフェースもサポートしています。
ReadContext クラスの read() メソッドを使用して、データベースから行を読み取ります。読み取るキーとキー範囲のコレクションを定義するには、KeySet オブジェクトを使用します。
データを読み取る方法は次のとおりです。
read 引数を使用してサンプルを実行します。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
read test-instance example-db
次のような出力が表示されます。
1 1 Total Junk
1 2 Go, Go, Go
2 1 Green
2 2 Forever Hold Your Peace
2 3 Terrified
データベース スキーマの更新
MarketingBudget という列を新たに Albums テーブルに追加する必要があるとします。既存のテーブルに新しい列を追加するには、データベース スキーマの更新が必要です。Spanner では、データベースでのトラフィックの処理中にデータベースのスキーマを更新できます。スキーマの更新では、データベースをオフラインにする必要がなく、テーブル全体あるいは列全体をロックすることもありません。スキーマの更新中もデータベースへのデータの書き込みを続けることができます。サポートされるスキーマの更新とスキーマ変更のパフォーマンスの詳細については、スキーマを更新するをご覧ください。
列を追加する
列を追加するには、コマンドラインで Google Cloud CLI を使用するか、プログラムから Java 用の Spanner クライアント ライブラリを使用します。
コマンドラインを使用する
テーブルに新しい列を追加するには、次の ALTER TABLE コマンドを使用します。
GoogleSQL
gcloud spanner databases ddl update example-db --instance=test-instance \
--ddl='ALTER TABLE Albums ADD COLUMN MarketingBudget INT64'
PostgreSQL
gcloud spanner databases ddl update example-db --instance=test-instance \
--ddl='ALTER TABLE Albums ADD COLUMN MarketingBudget BIGINT'
以下のように表示されます。
Schema updating...done.
Java 用の Spanner クライアント ライブラリを使用する
スキーマを変更するには、DatabaseAdminClient クラスの updateDatabaseDdl() メソッドを使用します。
GoogleSQL
PostgreSQL
addmarketingbudget 引数を使用してサンプルを実行します。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
addmarketingbudget test-instance example-db
以下のように表示されます。
Added MarketingBudget column.
新しい列へのデータの書き込み
次のコードは、新しい列にデータを書き込みます。MarketingBudget の値を、キーが Albums(1, 1) の行は 100000 に、キーが Albums(2, 2) の行は 500000 に設定します。
update 引数を使用してサンプルを実行します。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
update test-instance example-db
SQL クエリまたは読み取り呼び出しを実行して、書き込んだばかりの値を取得することもできます。
クエリを実行するコードを次に示します。
GoogleSQL
PostgreSQL
このクエリを実行するには、querymarketingbudget 引数を使用してサンプルを実行します。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
querymarketingbudget test-instance example-db
以下のように表示されます。
1 1 100000
1 2 NULL
2 1 NULL
2 2 500000
2 3 NULL
データの更新
読み取り / 書き込みトランザクションで DML を使用してデータを更新できます。
executeUpdate() メソッドを使用して DML ステートメントを実行します。
GoogleSQL
PostgreSQL
writewithtransactionusingdml 引数を使用してサンプルを実行します。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
writewithtransactionusingdml test-instance example-db
セカンダリ インデックスを使用する
Albums から AlbumTitle の値が特定の範囲内にある行すべてを取得すると仮定します。SQL ステートメントまたは読み取り呼び出しを使用して AlbumTitle 列からすべての値を読み取り、基準を満たしていない行を破棄することもできますが、このようなテーブル全体のスキャンは割高です(特に、行数が多いテーブルの場合)。代わりに、テーブルにセカンダリ インデックスを作成することにより、主キー以外の列を検索するときの行の取得速度を上げることができます。
既存のテーブルにセカンダリ インデックスを追加するには、スキーマの更新が必要です。他のスキーマの更新と同様に、Spanner ではデータベースがトラフィックを提供している間にインデックスを追加できます。Spanner では、インデックスに既存のデータが自動的にバックフィルされます。バックフィルには数分かかることがありますが、このプロセスの間に、データベースをオフラインにしたり、インデックス化対象のテーブルへの書き込みを控えたりする必要はありません。詳しくは、セカンダリ インデックスを追加するをご覧ください。
セカンダリ インデックスを追加すると、インデックスの効果により実行速度が上がりそうな SQL クエリに対してそのセカンダリ インデックスが自動的に使用されるようになります。読み取りインターフェースを使用する場合は、使用するインデックスを指定する必要があります。
セカンダリ インデックスを追加する
コマンドラインでインデックスを追加するには、gcloud CLI を使用するか、プログラムから Java 用の Spanner クライアント ライブラリを使用します。
コマンドラインを使用する
データベースにインデックスを追加するには、次の CREATE INDEX コマンドを使用します。
gcloud spanner databases ddl update example-db --instance=test-instance \
--ddl='CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)'
以下のように表示されます。
Schema updating...done.
Java 用の Spanner クライアント ライブラリを使用する
インデックスを追加するには、DatabaseAdminClient クラスの updateDatabaseDdl() メソッドを使用します。
addindex 引数を使用してサンプルを実行します。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
addindex test-instance example-db
インデックスの追加には数分かかる場合があります。インデックスが追加されると、次のように表示されます。
Added the AlbumsByAlbumTitle index.
インデックスを使用して読み取る
SQL クエリの場合、Spanner により適切なインデックスが自動的に使用されます。読み取りインターフェースでは、リクエストでインデックスを指定する必要があります。
読み取りインターフェースでインデックスを使用するには、ReadContext クラスの readUsingIndex() メソッドを使用します。
次のコードでは、インデックス AlbumsByAlbumTitle から AlbumId および AlbumTitle 列をすべて取得しています。
readindex 引数を使用してサンプルを実行します。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
readindex test-instance example-db
次のように表示されます。
2 Forever Hold Your Peace
2 Go, Go, Go
1 Green
3 Terrified
1 Total Junk
インデックス限定の読み取り用インデックスを追加する
前述の読み取り例には、MarketingBudget 列の読み取りが含まれていませんでした。これは、Spanner の読み取りインターフェースが、インデックスとデータテーブルを結合してインデックスに格納されていない値を検索する機能をサポートしていないためです。
MarketingBudget のコピーをインデックスに格納する AlbumsByAlbumTitle の代替定義を作成します。
コマンドラインから
GoogleSQL
gcloud spanner databases ddl update example-db --instance=test-instance \
--ddl='CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) STORING (MarketingBudget)
PostgreSQL
gcloud spanner databases ddl update example-db --instance=test-instance \
--ddl='CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) INCLUDE (MarketingBudget)
インデックスの追加には数分かかる場合があります。インデックスが追加されると、次のように表示されます。
Schema updating...done.
Java 用の Spanner クライアント ライブラリを使用する
GoogleSQL の場合は STORING 句、PostgreSQL の場合は INCLUDE 句を指定して、DatabaseAdminClient クラスの updateDatabaseDdl() メソッドを使用してインデックスを追加します。
GoogleSQL
PostgreSQL
addstoringindex 引数を使用してサンプルを実行します。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
addstoringindex test-instance example-db
インデックスの追加には数分かかる場合があります。インデックスが追加されると、次のように表示されます。
Added AlbumsByAlbumTitle2 index
これで、インデックス AlbumsByAlbumTitle2 から AlbumId、AlbumTitle、MarketingBudget 列をすべて取得する読み取りを実行できるようになりました。
readstoringindex 引数を使用してサンプルを実行します。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
readstoringindex test-instance example-db
次のような出力が表示されます。
2 Forever Hold Your Peace 300000
2 Go, Go, Go NULL
1 Green NULL
3 Terrified NULL
1 Total Junk 300000
読み取り専用トランザクションを使用したデータの取得
同じタイムスタンプで複数の読み取りを実行する場合について考えます。読み取り専用トランザクションはトランザクションの commit 履歴の整合性のあるプレフィックスを監視しているので、アプリケーションは常に整合性のあるデータを取得できます。読み取り専用トランザクションを実行するには、ReadOnlyTransaction オブジェクトを使用します。DatabaseClient クラスの readOnlyTransaction() メソッドを使用して、ReadOnlyTransaction オブジェクトを取得します。
次に示すのは、同じ読み取り専用トランザクションでクエリと読み取りを実行する方法です。
readonlytransaction 引数を使用してサンプルを実行します。
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
readonlytransaction test-instance example-db
次のような出力が表示されます。
2 2 Forever Hold Your Peace
1 2 Go, Go, Go
2 1 Green
2 3 Terrified
1 1 Total Junk
1 1 Total Junk
1 2 Go, Go, Go
2 1 Green
2 2 Forever Hold Your Peace
2 3 Terrified
クリーンアップ
このチュートリアルで使用したリソースについて Cloud 請求先アカウントに課金されないようにするため、作成したデータベースとインスタンスを削除します。
データベースの削除
インスタンスを削除すると、それに含まれるすべてのデータベースが自動的に削除されます。このステップでは、インスタンスを削除しないでデータベースを削除する方法を示します(インスタンスの料金は引き続き発生します)。
コマンドラインから
gcloud spanner databases delete example-db --instance=test-instance
Google Cloud コンソールの使用
Google Cloud コンソールの [Spanner インスタンス] ページに移動します。
インスタンスをクリックします。
削除するデータベースをクリックします。
[データベースの詳細] ページで [削除] をクリックします。
データベースを削除することを確認し、[削除] をクリックします。
インスタンスの削除
インスタンスを削除すると、そのインスタンスで作成されたすべてのデータベースが自動的に削除されます。
コマンドラインから
gcloud spanner instances delete test-instance
Google Cloud コンソールの使用
Google Cloud コンソールの [Spanner インスタンス] ページに移動します。
インスタンスをクリックします。
[削除] をクリックします。
インスタンスを削除することを確認し、[削除] をクリックします。
次のステップ
仮想マシン インスタンスで Spanner にアクセスする方法を確認する。
クライアント ライブラリを使用して Cloud サービスに対する認証を行うで、認可と認証について確認する。
Spanner のスキーマ設計のベスト プラクティスを確認する。