目標
このチュートリアルでは、Go 用の Spanner クライアント ライブラリを使用する以下の手順について説明します。
- Spanner のインスタンスとデータベースを作成します。
- データベースのデータに対し、書き込み、読み取り、SQL クエリの実行を行います。
- データベース スキーマを更新します。
- 読み取り / 書き込みトランザクションを使用してデータを更新します。
- セカンダリ インデックスをデータベースに追加します。
- インデックスを使用して、データの読み込みと SQL クエリの実行を行います。
- 読み取り専用トランザクションを使用してデータを取得します。
費用
このチュートリアルで使用する Spanner は、Google Cloud の有料コンポーネントです。Spanner を使用する際の料金については、料金をご覧ください。
始める前に
設定に示されている手順を完了します。この手順では、デフォルトの Google Cloud プロジェクトの作成と設定、課金の有効化、Cloud Spanner API の有効化、Cloud Spanner API の使用に必要な認証情報を取得するための OAuth 2.0 の設定について説明しています。
特に、ローカルの開発環境に認証情報を設定するために、必ず gcloud auth
application-default login
を実行してください。
ローカルの Go 環境を準備する
まだインストールしていない場合は開発マシンに Go(ダウンロード)をインストールします。
GOPATH
環境変数をまだ構成していない場合は、インストールをテストするの説明に沿って構成します。サンプルをマシンにダウンロードします。
git clone https://github.com/GoogleCloudPlatform/golang-samples $GOPATH/src/github.com/GoogleCloudPlatform/golang-samples
Spanner のサンプルコードが含まれるディレクトリに移動します。
cd $GOPATH/src/github.com/GoogleCloudPlatform/golang-samples/spanner/spanner_snippets
環境変数
GCLOUD_PROJECT
に Google Cloud プロジェクト ID を設定します。export GCLOUD_PROJECT=[MY_PROJECT_ID]
インスタンスを作成する
Spanner を最初に使用する場合は、インスタンスを作成する必要があります。インスタンスとは、Spanner データベースによって使用されるリソースの割り当てのことです。インスタンスを作成するときは、インスタンス構成を選択してデータの格納場所を指定し、さらに使用するノード数も選択して、インスタンスの配信リソースおよびストレージ リソースの量を決定します。
次のコマンドを実行して、1 ノードの us-central1
リージョンに Spanner インスタンスを作成します。
gcloud spanner instances create test-instance --config=regional-us-central1 \
--description="Test Instance" --nodes=1
これにより、次の特性を持つインスタンスが作成されます。
- インスタンス ID
test-instance
- 表示名
Test Instance
- インスタンス構成
regional-us-central1
(リージョン構成ではデータが単一のリージョンに保存され、マルチリージョン構成ではデータが複数のリージョンに分散されます。詳しくは、インスタンスについてをご覧ください)。 - ノード数 1(
node_count
はインスタンスのデータベースで使用可能な配信リソースとストレージ リソースの量に対応します。詳しくは、ノードと処理ユニットをご覧ください)。
次のように表示されます。
Creating instance...done.
サンプル ファイルの確認
サンプル リポジトリには、Go で Spanner を使用する方法を示すサンプルが含まれています。
snippet.go
ファイルを見ると、Spanner の使用方法を確認できます。このファイルのコードでは、新しいデータベースを作成して使用する方法が示されています。データで使用しているサンプル スキーマは、スキーマとデータモデルのページにあります。
データベースの作成
コマンドラインで次のコマンドを実行して、test-instance
というインスタンスに example-db
というデータベースを作成します。
GoogleSQL
go run snippet.go createdatabase projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
PostgreSQL
go run snippet.go pgcreatedatabase projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
次のように表示されます。
Created database [example-db]
GoogleSQL
PostgreSQL
次のステップでは、データベースにデータを書き込みます。
データベース クライアントの作成
読み取りまたは書き込みを行うには、その前にClient
を作成する必要があります。
Client
はデータベース接続と考えることができます。Spanner とのすべてのやり取りは Client
を経由する必要があります。通常はアプリケーション開始時に Client
を作成し、読み取り、書き込み、トランザクションの実行に Client
を再利用します。それぞれのクライアントが、Spanner のリソースを使用します。
同じアプリで複数のクライアントを作成する場合は、Client.Close()
を呼び出し、必要がなくなったらすぐにクライアントのリソース(ネットワーク接続を含む)をクリーンアップする必要があります。
詳細については、Client
のリファレンスをご覧ください。
前の例のコードは、データベースの作成に使用される DatabaseAdminClient
の作成方法も示しています。
DML でのデータの書き込み
読み取り / 書き込みトランザクションでデータ操作言語(DML)を使用してデータを挿入できます。
Update()
メソッドを使用して DML ステートメントを実行します。
GoogleSQL
PostgreSQL
Google SQL の dmlwrite
引数と、PostgreSQL の pgdmlwrite
引数を使用してサンプルを実行します:
GoogleSQL
go run snippet.go dmlwrite projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
PostgreSQL
go run snippet.go pgdmlwrite projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
次のように表示されます。
4 record(s) inserted.
ミューテーションを使用してデータを書き込む
ミューテーションを使ってデータを挿入することもできます。
Mutation
はミューテーション オペレーションのコンテナです。Mutation
は、Spanner データベース内のさまざまな行やテーブルに対して、Spanner によってアトミックに適用される一連の操作(挿入、更新、削除)を表します。
Mutation.InsertOrUpdate()
を使用して INSERT_OR_UPDATE
ミューテーションを作成できます。これによって新しい行が追加されます。行がすでに存在している場合は列値が更新されます。あるいは、Mutation.Insert()
メソッドを使用して、新しい行を追加する INSERT
ミューテーションを作成します。
Client.Apply()
を使用してデータベースにミューテーションをアトミックに適用します。
次のコードは、ミューテーションを使用してデータを書き込む方法を示しています。
write
引数を使用してサンプルを実行します。
go run snippet.go write projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
コマンドが正常に実行されることを確認します。
SQL を使用したデータのクエリ
Spanner では、データの読み取り用に SQL インターフェースがサポートされています。このインターフェースにアクセスするには、コマンドラインで Google Cloud CLI を使用するか、プログラムで Go 用の 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
Go 用の Spanner クライアント ライブラリを使用する
コマンドラインで SQL ステートメントを実行するだけでなく、Go 用の Spanner クライアント ライブラリを使用して同じ SQL ステートメントをプログラマティックに発行できます。
SQL クエリの実行に使用されるメソッドとタイプを次に示します。Client.Single()
: Spanner テーブルの 1 つ以上の行から 1 つ以上の列の値を読み取るために使用します。Client.Single
は、読み取りまたは SQL ステートメントを実行するために使用されるReadOnlyTransaction
を返します。ReadOnlyTransaction.Query()
: このメソッドは、データベースに対してクエリを実行するために使用します。Statement
タイプ: SQL 文字列を作成するために使用します。Row
タイプ: SQL ステートメントまたは読み取り呼び出しから返されるデータにアクセスするために使用します。
クエリを発行してデータにアクセスする方法を次に示します。
query
引数を使用してサンプルを実行します。
go run snippet.go query projects/$GCLOUD_PROJECT/instances/test-instance/databases/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
Google SQL の querywithparameter
引数と、PostgreSQL の pgqueryparameter
引数を使用してサンプルを実行します。
GoogleSQL
go run snippet.go querywithparameter projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
PostgreSQL
go run snippet.go pgqueryparameter projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
次のような出力が表示されます。
12 Melissa Garcia
読み取り API を使用したデータの読み込み
Spanner の SQL インターフェースに加えて、Spanner では読み取りインターフェースもサポートしています。
ReadOnlyTransaction.Read()
を使用して、データベースから行を読み取ります。読み取るキーおよびキー範囲のコレクションを定義するには、KeySet
を使用します。
データを読み取る方法を次に示します。
read
引数を使用してサンプルを実行します。
go run snippet.go read projects/$GCLOUD_PROJECT/instances/test-instance/databases/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 を使用するか、プログラムから Go 用の 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.
Go 用の Spanner クライアント ライブラリを使用する
スキーマを変更するには、DatabaseAdminClient.UpdateDatabaseDdl()
を使用します。
GoogleSQL
PostgreSQL
Google SQL の addnewcolumn
引数と、PostgreSQL の pgaddnewcolumn
引数を使用してサンプルを実行します。
GoogleSQL
go run snippet.go addnewcolumn projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
PostgreSQL
go run snippet.go pgaddnewcolumn projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
次のように表示されます。
Added MarketingBudget column.
新しい列へのデータの書き込み
次のコードは、新しい列にデータを書き込みます。MarketingBudget
の値を、キーが Albums(1, 1)
の行は 100000
に、キーが Albums(2, 2)
の行は 500000
に設定します。
update
引数を使用してサンプルを実行します。
go run snippet.go update projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
SQL クエリまたは読み取り呼び出しを実行して、書き込んだばかりの値を取得することもできます。
クエリを実行するコードを次に示します。
GoogleSQL
PostgreSQL
このクエリを実行するには、Google SQL の querynewcolumn
引数と、PostgreSQL の pgquerynewcolumn
引数を使用してサンプルを実行します。
GoogleSQL
go run snippet.go querynewcolumn projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
PostgreSQL
go run snippet.go pgquerynewcolumn projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
次のように表示されます。
1 1 100000
1 2 NULL
2 1 NULL
2 2 500000
2 3 NULL
データの更新
読み取り / 書き込みトランザクションで DML を使用してデータを更新できます。
Update()
メソッドを使用して DML ステートメントを実行します。
GoogleSQL
PostgreSQL
dmlwritetxn
引数を使用してサンプルを実行します。
go run snippet.go dmlwritetxn projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
次のように表示されます。
Moved 200000 from Album2's MarketingBudget to Album1's.
注:セカンダリ インデックスの使用
Albums
から AlbumTitle
の値が特定の範囲内にある行すべてを取得すると仮定します。SQL ステートメントまたは読み取り呼び出しを使用して AlbumTitle
列からすべての値を読み取り、基準を満たしていない行を破棄することもできますが、このようなテーブル全体のスキャンは割高です(特に、行数が多いテーブルの場合)。代わりに、テーブルにセカンダリ インデックスを作成することにより、主キー以外の列を検索するときの行の取得速度を上げることができます。
既存のテーブルにセカンダリ インデックスを追加するには、スキーマの更新が必要です。他のスキーマの更新と同様に、Spanner ではデータベースがトラフィックの処理を継続している間にインデックスを追加できます。Spanner では、インデックスに既存のデータが自動的にバックフィルされます。バックフィルには数分かかることがありますが、このプロセスの間に、データベースをオフラインにしたり、インデックス化対象のテーブルへの書き込みを控えたりする必要はありません。詳しくは、セカンダリ インデックスを追加するをご覧ください。
セカンダリ インデックスを追加すると、インデックス効果で実行速度が上がりそうな SQL クエリに対して Spanner ではそのセカンダリ インデックスが自動的に使用されるようになります。読み取りインターフェースを使用する場合は、使用するインデックスを指定する必要があります。
セカンダリ インデックスの追加
インデックスを追加するには、コマンドラインで gcloud CLI を使用するか、Go 用 Spanner クライアント ライブラリを使用してプログラムによって行います。
コマンドラインから
データベースにインデックスを追加するには、次の CREATE INDEX
コマンドを使用します。
gcloud spanner databases ddl update example-db --instance=test-instance \
--ddl='CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)'
次のように表示されます。
Schema updating...done.
Go 用 Spanner クライアント ライブラリの使用
インデックスを追加するには、UpdateDatabaseDdl()
を使用します。
インデックスの追加には数分かかる場合があります。インデックスが追加されると、次のように表示されます。
Added index
インデックスを使用して読み取りを行う
SQL クエリの場合は、Spanner により適切なインデックスが自動的に使用されます。読み取りインターフェースでは、リクエストでインデックスを指定する必要があります。
読み取りインターフェースでインデックスを使用するには、ReadOnlyTransaction.ReadUsingIndex()
を使用し、インデックスを指定してデータベースから 0 行以上の値を読み取ります。
次のコードでは、インデックス AlbumsByAlbumTitle
から AlbumId
および AlbumTitle
列をすべて取得しています。
readindex
引数を使用してサンプルを実行します。
go run snippet.go readindex projects/$GCLOUD_PROJECT/instances/test-instance/databases/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.
Go 用 Spanner クライアント ライブラリの使用
UpdateDatabaseDdl()
を使用して、GoogleSQL の場合は STORING
句、PostgreSQL の場合は INCLUDE
句を指定してインデックスを追加します。
GoogleSQL
PostgreSQL
addstoringindex
引数を使用してサンプルを実行します。
GoogleSQL
go run snippet.go addstoringindex projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
PostgreSQL
go run snippet.go pgaddstoringindex projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db
インデックスの追加には数分かかる場合があります。インデックスが追加されると、次のように表示されます。
Added storing index
これで、インデックス AlbumsByAlbumTitle2
から AlbumId
、AlbumTitle
、MarketingBudget
列をすべて取得する読み取りを実行できるようになりました。
readstoringindex
引数を使用してサンプルを実行します。
go run snippet.go readstoringindex projects/$GCLOUD_PROJECT/instances/test-instance/databases/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
タイプを使用します。Client.ReadOnlyTransaction()
を使用して ReadOnlyTransaction
を取得します。
同じ読み取り専用トランザクションでクエリと読み取りを実行する方法を次に示します。
readonlytransaction
引数を使用してサンプルを実行します。
go run snippet.go readonlytransaction projects/$GCLOUD_PROJECT/instances/test-instance/databases/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 のスキーマ設計のベスト プラクティスを確認する。