目標
本教學課程將逐步引導您使用 C++ 專用的 Spanner 用戶端程式庫完成下列步驟:
- 建立 Spanner 執行個體和資料庫。
- 對資料庫中的資料進行寫入和讀取,以及執行 SQL 查詢。
- 更新資料庫結構定義。
- 使用讀取/寫入交易來更新資料。
- 將次要索引新增至資料庫。
- 使用索引對資料執行讀取作業和 SQL 查詢。
- 使用唯讀交易擷取資料。
費用
本教學課程使用 Spanner,這是Google Cloud的計費元件。如要瞭解 Spanner 的使用費用,請參閱「定價」一文。
事前準備
完成「設定」一文中說明的步驟,包含建立與設定預設的 Google Cloud 專案、啟用計費功能、啟用 Cloud Spanner API 和設定 OAuth 2.0 以取得使用 Cloud Spanner API 的驗證憑證。
特別提醒您,請務必執行 gcloud auth
application-default login
來設定本機開發環境的驗證憑證。
準備本機 C++ 環境
將應用程式存放區範例複製到本機電腦中:
git clone https://github.com/googleapis/google-cloud-cpp $HOME/google-cloud-cpp
請按照這些操作說明安裝 Linux 版 Bazel。
變更為包含 Spanner 範例程式碼的目錄:
cd $HOME/google-cloud-cpp
請使用以下指令建構範例:
bazel build //google/cloud/spanner/samples:samples
為
google-cloud-cpp
專案設定驗證和授權。gcloud auth application-default login
建立名為
GCLOUD_PROJECT
的環境變數。將 [MY_PROJECT_ID] 替換為您的 Google Cloud 專案 ID。您可以在專案的「歡迎」頁面中找到這個 ID。export GCLOUD_PROJECT=[MY_PROJECT_ID]
建立執行個體
首次使用 Spanner 時,您必須建立執行個體,這是 Spanner 資料庫會使用的資源分配單位。建立執行個體時,請選擇「執行個體設定」以決定資料儲存的位置,再選擇要使用的節點數量以決定執行個體的服務和儲存空間資源量。
執行下列指令,在 us-central1
地區使用 1 個節點建立 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.
瀏覽範例檔案
範例存放區中包含一個範例,說明如何透過 C++ 使用 Spanner。
請查看 google/cloud/spanner/samples/samples.cc
檔案,瞭解如何建立資料庫及修改資料庫結構定義。這份資料會使用結構定義與資料模型頁面中所列出的範例結構定義。
建立資料庫
GoogleSQL
bazel run //google/cloud/spanner/samples:samples -- \
create-database $GCLOUD_PROJECT test-instance example-db
PostgreSQL
bazel run //google/cloud/spanner/samples:postgresql_samples -- \
create-database $GCLOUD_PROJECT test-instance example-db
bazel run //google/cloud/spanner/samples:postgresql_samples -- \
interleaved-table $GCLOUD_PROJECT test-instance example-db
畫面上會顯示下列訊息:
Created database [projects/${GCLOUD_PROJECT}/instances/test-instance/databases/example-db]
GoogleSQL
PostgreSQL
在 PostgreSQL 方言中,您必須先建立資料庫,才能提交 DDL 要求來建立資料表。
以下範例會建立資料庫:
以下範例會在資料庫中建立兩個資料表:
下一個步驟是將資料寫入資料庫。
建立資料庫用戶端
您必須先建立 Client
,才能執行讀取或寫入作業:
Client
可讓您讀取、寫入、查詢及執行 Spanner 資料庫上的交易。一般而言,您會在應用程式啟動時建立 Client
,接著重複使用該 Client
進行讀取、寫入及執行交易。每個用戶端都會使用 Spanner 中的資源。Client
的析構函式會自動清除 Client
資源,包括網路連線。
如要進一步瞭解 Client
,請參閱 Google Cloud Spanner C++ 參考資料。
使用 DML 寫入資料
您可以使用資料操縱語言 (DML) 在讀寫交易中插入資料。
您可以使用 Client::ExecuteDml()
函式執行 DML 陳述式。
使用 getting-started-insert
引數執行範例。
bazel run //google/cloud/spanner/samples:samples -- \
getting-started-insert $GCLOUD_PROJECT test-instance example-db
畫面上會顯示下列訊息:
Insert was successful [spanner_dml_getting_started_insert]
使用變異寫入資料
您也可以使用變異來插入資料。
您可以利用 Client
物件寫入資料。Client::Commit()
函式會建立並修訂寫入作業的交易,在資料庫的資料欄、資料列與資料表中,以不可分割的形式在單一邏輯點及時執行這些寫入作業。
此程式碼顯示如何使用變異寫入資料:
使用 insert-data
引數執行範例。
bazel run //google/cloud/spanner/samples:samples -- \
insert-data $GCLOUD_PROJECT test-instance example-db
畫面上會顯示下列訊息:
Insert was successful [spanner_insert_data]
使用 SQL 查詢資料
Spanner 支援可用於讀取資料的 SQL 介面。您可以透過 Google Cloud CLI 在指令列上存取介面,或使用適用於 C++ 的 Spanner 用戶端程式庫以程式輔助方式存取介面。
使用指令列
執行下列 SQL 陳述式,從 Albums
資料表讀取所有資料欄的值:
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
使用 C++ 專用的 Spanner 用戶端程式庫
除了在指令列上執行 SQL 陳述式外,您也可以使用 C++ 專用的 Spanner 用戶端程式庫,以程式輔助方式發出相同的 SQL 陳述式。
您可以使用 Client::ExecuteQuery()
函式執行 SQL 查詢。下面說明如何發出查詢和存取資料:
使用 query_data
引數執行範例。
bazel run //google/cloud/spanner/samples:samples -- \
query-data $GCLOUD_PROJECT test-instance example-db
畫面上應會顯示下列結果:
SingerId: 1 LastName: Richards
SingerId: 2 LastName: Smith
SingerId: 3 LastName: Trentor
SingerId: 4 LastName: Martin
SingerId: 5 LastName: Lomond
SingerId: 12 LastName: Garcia
SingerId: 13 LastName: Morales
SingerId: 14 LastName: Long
SingerId: 15 LastName: Shaw
使用 SQL 參數執行查詢
如果應用程式有經常執行的查詢,您可以透過參數化來提升效能。系統可快取並重新使用產生的參數查詢,減少編譯的成本。詳情請參閱「使用查詢參數,針對經常執行的查詢加快速度」。
以下範例說明如何在 WHERE
子句中使用參數,查詢包含 LastName
特定值的記錄。
使用 query-with-parameter 指令執行範例。
bazel run //google/cloud/spanner/samples:samples -- \
query-with-parameter $GCLOUD_PROJECT test-instance example-db
畫面上應會顯示下列結果:
SingerId: 12 FirstName: Melissa LastName: Garcia
使用讀取 API 讀取資料
除了 Spanner 的 SQL 介面外,Spanner 也支援讀取介面。
您可以使用 Client::Read()
函式讀取資料庫中的資料列。使用 KeySet
物件定義要讀取的索引鍵集合和索引鍵範圍。
下列內容將示範如何讀取資料:
使用 read-data
引數執行範例。
bazel run //google/cloud/spanner/samples:samples -- \
read-data $GCLOUD_PROJECT test-instance example-db
畫面會顯示類似以下的輸出:
SingerId: 1, AlbumId: 1, AlbumTitle: Total Junk
SingerId: 1, AlbumId: 2, AlbumTitle: Go, Go, Go
SingerId: 2, AlbumId: 1, AlbumTitle: Green
SingerId: 2, AlbumId: 2, AlbumTitle: Forever Hold Your Peace
SingerId: 2, AlbumId: 3, AlbumTitle: Terrified
更新資料庫結構定義
假設您需要新增名稱為 MarketingBudget
的新資料欄到 Albums
資料表,必須先更新資料庫結構定義,才能新增新資料欄到現有的資料表。Spanner 可在資料庫持續處理流量時,支援資料庫的結構定義更新作業。結構定義更新作業不需要讓資料庫離線,也不會鎖定整個資料表或資料欄;您可以在結構定義更新期間持續將資料寫入資料庫。詳情請參閱進行結構定義更新一文中支援的結構定義更新和結構定義變更效能。
新增資料欄
您可以使用 Google Cloud CLI 在指令列中新增資料欄,或使用 C++ 專屬的 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.
使用 C++ 專用的 Spanner 用戶端程式庫
使用 DatabaseAdminClient::UpdateDatabase()
函式修改結構定義。
使用 add-column
指令執行範例。
bazel run //google/cloud/spanner/samples:samples -- \
add-column $GCLOUD_PROJECT test-instance example-db
畫面上會顯示下列訊息:
Added MarketingBudget column
寫入資料到新資料欄
以下程式碼會將資料寫入新資料欄,並在 Albums(1, 1)
和 Albums(2, 2)
這兩個索引鍵表示的資料列中將 MarketingBudget
分別設為 100000
和 500000
。
使用 update-data
引數執行範例。
bazel run //google/cloud/spanner/samples:samples -- \
update-data $GCLOUD_PROJECT test-instance example-db
您也可以執行 SQL 查詢或讀取呼叫,以擷取剛寫入的值。
以下是執行查詢的程式碼:
如要執行這項查詢,請使用 query-new-column
引數執行範例檔案。
bazel run //google/cloud/spanner/samples:samples -- \
query-new-column $GCLOUD_PROJECT test-instance example-db
畫面上會顯示下列訊息:
SingerId: 1 AlbumId: 1 MarketingBudget: 100000
SingerId: 1 AlbumId: 2 MarketingBudget: NULL
SingerId: 2 AlbumId: 1 MarketingBudget: NULL
SingerId: 2 AlbumId: 2 MarketingBudget: 500000
SingerId: 2 AlbumId: 3 MarketingBudget: NULL
更新資料
您可以在讀寫交易中使用 DML 來更新資料。
您可以使用 Client::ExecuteDml()
函式執行 DML 陳述式。
使用 getting-started-update
引數執行範例。
bazel run //google/cloud/spanner/samples:samples -- \
getting-started-update $GCLOUD_PROJECT test-instance example-db
畫面上會顯示下列訊息:
Update was successful [spanner_dml_getting_started_update]
使用次要索引
假設您要針對 Albums
擷取 AlbumTitle
值在特定範圍內的所有資料列,可以先利用 SQL 陳述式或讀取呼叫,從 AlbumTitle
資料欄讀取所有值,然後再捨棄條件不符的資料列。不過,執行完整資料表掃描的費用高昂,對於內含大量資料列的資料表而言更是如此。因此您可以改為在資料表建立次要索引,以在將非主鍵資料欄做為搜尋條件時,能加快資料列的擷取速度。
您必須先更新結構定義,才能將次要索引新增至現有資料表。如同其他結構定義更新,Spanner 支援在資料庫持續處理流量時新增索引。Spanner 會自動使用現有資料填入索引。補充作業可能需要幾分鐘才能完成,但您不必將資料庫設為離線,也不必避免在這個程序中寫入已編入索引的資料表。詳情請參閱「新增次要索引」。
新增次要索引後,Spanner 會自動將其用於 SQL 查詢,這些查詢可能會在使用索引後執行得更快。如果您使用讀取介面,則必須指定要使用的索引。
新增次要索引
您可以使用 gcloud CLI 在指令列上新增索引,或以程式輔助方式,使用 C++ 專屬的 Spanner 用戶端程式庫新增索引。
使用指令列
使用下列 CREATE INDEX
指令,在資料庫中新增索引:
gcloud spanner databases ddl update example-db --instance=test-instance \
--ddl='CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)'
畫面上會顯示下列訊息:
Schema updating...done.
使用 C++ 專用的 Spanner 用戶端程式庫
您可以使用 DatabaseAdminClient::UpdateDatabase()
函式新增索引:
使用 add-index
引數執行範例。
bazel run //google/cloud/spanner/samples:samples -- \
add-index $GCLOUD_PROJECT test-instance example-db
索引可能需要幾分鐘才能新增完成。加入索引後,畫面上會顯示類似以下的輸出內容:
`AlbumsByAlbumTitle` Index successfully added, new DDL:
database: "projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db"
statements: "CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)"
commit_timestamps {
seconds: 1581011550
nanos: 531102000
}
使用索引進行讀取
對於 SQL 查詢,Spanner 會自動使用適當的索引。在讀取介面中,您必須在要求中指定索引。
如要在讀取介面中使用索引,請使用 Client::Read()
函式,透過索引從資料庫讀取零個或多個資料列。
下列程式碼會從 AlbumsByAlbumTitle
索引中擷取所有 AlbumId
和 AlbumTitle
資料欄。
使用 read-data-with-index
引數執行範例。
bazel run //google/cloud/spanner/samples:samples -- \
read-data-with-index $GCLOUD_PROJECT test-instance example-db
畫面上會顯示下列訊息:
AlbumId: 2 AlbumTitle: Forever Hold Your Peace
AlbumId: 2 AlbumTitle: Go, Go, Go
AlbumId: 1 AlbumTitle: Green
AlbumId: 3 AlbumTitle: Terrified
AlbumId: 1 AlbumTitle: Total Junk
新增索引以便僅讀取索引
您可能已經注意到,前述的讀取範例並未包含讀取 MarketingBudget
資料欄。這是因為 Spanner 的讀取介面不支援將索引與資料表彙整,再查詢未保存於索引中的值。
請為 AlbumsByAlbumTitle
建立替代定義,將 MarketingBudget
的副本保存在索引中。
使用指令列
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.
使用 C++ 專用的 Spanner 用戶端程式庫
您可以使用 DatabaseAdminClient::UpdateDatabase()
函式,為 STORING
子句新增索引:
使用 add-storing-index
引數執行範例。
bazel run //google/cloud/spanner/samples:samples -- \
add-storing-index $GCLOUD_PROJECT test-instance example-db
畫面會顯示類似以下的輸出:
`AlbumsByAlbumTitle2` Index successfully added, new DDL:
database: "projects/$GCLOUD_PROJECT/instances/test-instance/databases/example-db"
statements: "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) STORING (MarketingBudget)"
commit_timestamps {
seconds: 1581012328
nanos: 416682000
}
現在您可以執行讀取作業,從 AlbumsByAlbumTitle2
索引中擷取所有 AlbumId
、AlbumTitle
和 MarketingBudget
欄:
您可以執行查詢,藉此明確指定使用先前建立的儲存索引來讀取資料:
使用 read-data-with-storing-index
引數執行範例。
bazel run //google/cloud/spanner/samples:samples -- \
read-data-with-storing-index $GCLOUD_PROJECT test-instance example-db
畫面會顯示類似以下的輸出:
AlbumId: 2 AlbumTitle: Forever Hold Your Peace MarketingBudget: 520000
AlbumId: 2 AlbumTitle: Go, Go, Go MarketingBudget: NULL
AlbumId: 1 AlbumTitle: Green MarketingBudget: NULL
AlbumId: 3 AlbumTitle: Terrified MarketingBudget: NULL
AlbumId: 1 AlbumTitle: Total Junk MarketingBudget: 80000
使用唯讀交易擷取資料
假設您想要在相同時間戳記執行一次以上的讀取作業。唯讀交易會觀察出交易修訂記錄中一致的前置字串,讓應用程式取得的資料始終保持一致。Transaction
類型用於代表所有類型的交易。使用 MakeReadOnlyTransaction()
工廠函式建立唯讀交易。
以下顯示如何執行查詢,並在同一個唯讀交易中執行讀取作業:
使用 read-only-transaction
引數執行範例。
bazel run //google/cloud/spanner/samples:samples -- \
read-only-transaction $GCLOUD_PROJECT test-instance example-db
畫面會顯示類似以下的輸出:
Read 1 results
SingerId: 2 AlbumId: 2 AlbumTitle: Forever Hold Your Peace
SingerId: 1 AlbumId: 2 AlbumTitle: Go, Go, Go
SingerId: 2 AlbumId: 1 AlbumTitle: Green
SingerId: 2 AlbumId: 3 AlbumTitle: Terrified
SingerId: 1 AlbumId: 1 AlbumTitle: Total Junk
Read 2 results
SingerId: 2 AlbumId: 2 AlbumTitle: Forever Hold Your Peace
SingerId: 1 AlbumId: 2 AlbumTitle: Go, Go, Go
SingerId: 2 AlbumId: 1 AlbumTitle: Green
SingerId: 2 AlbumId: 3 AlbumTitle: Terrified
SingerId: 1 AlbumId: 1 AlbumTitle: Total Junk
清除所用資源
如要避免系統向您的 Cloud Billing 帳戶收取您在本教學課程中所用資源的額外費用,請捨棄資料庫並刪除您建立的執行個體。
刪除資料庫
您刪除執行個體時,也會自動刪除其中所有資料庫。這個步驟將示範如何在保留執行個體的情況下刪除資料庫 (您仍須支付執行個體費用)。
使用指令列
gcloud spanner databases delete example-db --instance=test-instance
使用 Google Cloud 主控台
前往 Google Cloud 控制台的「Spanner 執行個體」頁面。
點選執行個體。
點選您要刪除的資料庫。
在「Database details」(資料庫詳細資料) 頁面,按一下 [Delete] (刪除)。
確認您要刪除資料庫,然後按一下 [Delete] (刪除)。
刪除執行個體
您刪除執行個體時,也會自動捨棄您在其中建立的所有資料庫。
使用指令列
gcloud spanner instances delete test-instance
使用 Google Cloud 主控台
前往 Google Cloud 控制台的「Spanner 執行個體」頁面。
點選執行個體。
按一下 [Delete] (刪除)。
確認您要刪除執行個體,然後按一下 [Delete] (刪除)。
後續步驟
瞭解如何透過虛擬機器執行個體存取 Spanner。
請參閱「使用用戶端程式庫驗證 Cloud 服務」一文,進一步瞭解授權和驗證憑證。
進一步瞭解 Spanner 的結構定義設計最佳做法。