關(guān)于 Cloud Spanner,DBA(數(shù)據(jù)庫管理員)需要了解哪些內(nèi)容?

來源: Google Cloud
作者:Google Cloud
時(shí)間:2021-03-19
17688
Cloud Spanner 是一項(xiàng)關(guān)系型、支持水平擴(kuò)展的數(shù)據(jù)庫服務(wù),基于云端分布式設(shè)計(jì)構(gòu)建,可為開發(fā)者和數(shù)據(jù)庫管理員(DBA)提高效率,具有高可用性,且在結(jié)構(gòu)上區(qū)別于典型數(shù)據(jù)庫。在本系列博客中,我們將探討 DBA 和開發(fā)者在從傳統(tǒng)的垂直擴(kuò)展關(guān)系型數(shù)據(jù)庫的管理系統(tǒng)(RDBMS),遷移到 Cloud Spanner 時(shí),可能遇到的關(guān)鍵不同。我們并進(jìn)一步討論哪些是該做的,哪些是不該做的,最佳實(shí)踐是什么,以及 Cloud Spanner 中存在這種不同的原因。

Cloud Spanner 是一項(xiàng)關(guān)系型、支持水平擴(kuò)展的數(shù)據(jù)庫服務(wù),基于云端/分布式設(shè)計(jì)構(gòu)建,可為開發(fā)者和數(shù)據(jù)庫管理員(DBA)提高效率,具有高可用性,且在結(jié)構(gòu)上區(qū)別于典型數(shù)據(jù)庫。在本系列博客中,我們將探討 DBA 和開發(fā)者在從傳統(tǒng)的垂直擴(kuò)展關(guān)系型數(shù)據(jù)庫的管理系統(tǒng)(RDBMS),遷移到 Cloud Spanner 時(shí),可能遇到的關(guān)鍵不同。我們并進(jìn)一步討論哪些是該做的,哪些是不該做的,最佳實(shí)踐是什么,以及 Cloud Spanner 中存在這種不同的原因。

在本系列中,我們會(huì)就一系列主題進(jìn)行探討,包括:

鍵的選擇和索引的使用

如何匹配業(yè)務(wù)邏輯

導(dǎo)入和導(dǎo)出數(shù)據(jù)

從現(xiàn)有的 RDBMS 中遷移

性能優(yōu)化

訪問控制和日志記錄

您將了解如何更好地使用 Cloud Spanner,讓其在海量數(shù)據(jù)庫中實(shí)現(xiàn)線性性能擴(kuò)展。在第一部分,我們先來詳細(xì)了解一下 Cloud Spanner 中鍵和索引的概念。

在 Cloud Spanner 中選擇鍵

與其他數(shù)據(jù)庫類似,鍵的選擇對(duì)于優(yōu)化數(shù)據(jù)庫的性能至關(guān)重要。鑒于 Cloud Spanner 分配數(shù)據(jù)庫負(fù)載的機(jī)制,因此鍵的選擇對(duì)其來說更為重要。與傳統(tǒng) RDBMS 不同的是,在選擇表(Table)的主鍵和要索引的列(Column)時(shí),你需要格外注意。

使用分布恰當(dāng)?shù)逆I會(huì)使表的大小和性能隨著Cloud Spanner 節(jié)點(diǎn)數(shù)量線性擴(kuò)展,而使用分布不良的鍵會(huì)導(dǎo)致熱點(diǎn)問題,即一個(gè)節(jié)點(diǎn)承擔(dān)表的大部分讀和寫。

在傳統(tǒng)的垂直擴(kuò)展 RDBMS 中,單個(gè)節(jié)點(diǎn)管理所有表。(根據(jù)安裝的不同,可能會(huì)有副本,用于讀取或故障轉(zhuǎn)移)。因此,該單個(gè)節(jié)點(diǎn)完全控制表格的行鎖(row lock)和從數(shù)字序列(numberic sequence)中生成的唯一鍵。

Cloud Spanner 是一個(gè)分布式系統(tǒng),在任何時(shí)候都會(huì)有很多節(jié)點(diǎn)對(duì)數(shù)據(jù)庫進(jìn)行讀寫。但是,為了實(shí)現(xiàn)可擴(kuò)展性、全局 ACID 事務(wù)和強(qiáng)一致性,只有一個(gè)節(jié)點(diǎn)可以隨時(shí)對(duì)給定的行進(jìn)行寫入。

Cloud Spanner 通過使用按照字典序排序的主鍵的范圍,將每個(gè)表拆分成若干個(gè)分片,從而讓表的行的管理分布在多個(gè)節(jié)點(diǎn)上。

這使得 Cloud Spanner 能夠?qū)崿F(xiàn)高可用性和可擴(kuò)展性,但這也意味著使用任何連續(xù)增加或減少的序列作為主鍵,都不利于性能。為了解釋原因,讓我們來探討一下 Cloud Spanner 是如何創(chuàng)建和管理表的分片的。

表格拆分和鍵的選擇

Cloud Spanner 使用 Paxos 管理分片(您可以通過以下文檔了解詳情:Cloud Spanner 的讀寫生命周期 和 Spanner: Google 的全球式分布式數(shù)據(jù)庫)。) 在 Cloud Spanner 區(qū)域?qū)嵗校x取/寫入每個(gè)分片的責(zé)任被分配到一組三個(gè)節(jié)點(diǎn)上,分別位于 Cloud Spanner 實(shí)例的三個(gè)可用性地區(qū)中。

這個(gè)組中的一個(gè)節(jié)點(diǎn)被選為「Split Leader」,負(fù)責(zé)管理分片中所有行的寫入和鎖定。該組中的三個(gè)節(jié)點(diǎn)都可以進(jìn)行讀取。

為了創(chuàng)建一個(gè)比較直觀的例子,我們假設(shè)有一個(gè) 600 行的表,該表格使用簡(jiǎn)單、連續(xù)、遞增的整數(shù)鍵(類似傳統(tǒng) RDBMS 中常見的那樣),這個(gè)表被拆分為 6 個(gè)分片,運(yùn)行在一個(gè)雙節(jié)點(diǎn)(每個(gè)地區(qū))Cloud Spanner 實(shí)例上。在理想情況下,該表會(huì)有六個(gè)分片,其中的 Leaders 將是實(shí)例中可用的六個(gè)單獨(dú)節(jié)點(diǎn)。

ia_12100000002.png

只要讀取和更新均勻地分布在鍵范圍之內(nèi),這種分布就會(huì)提供理想的讀寫性能。

熱點(diǎn)問題

當(dāng)新行被添加到數(shù)據(jù)庫時(shí),問題就出現(xiàn)了。每一條新的行都會(huì)有一個(gè)遞增的ID,并且會(huì)被添加到最后一個(gè)分片,這意味著在六個(gè)可用的節(jié)點(diǎn)中,只有一個(gè)節(jié)點(diǎn)會(huì)處理所有的寫入。在上面的例子中,節(jié)點(diǎn) 2c 將處理所有的寫入。如此一來,這個(gè)節(jié)點(diǎn)就會(huì)成為一個(gè)熱點(diǎn),限制了數(shù)據(jù)庫的整體寫入性能。此外,行的分布也會(huì)變得不平衡,最后一個(gè)拆分會(huì)明顯變大,因此它會(huì)處理更多的行讀取。

為了補(bǔ)償不平衡的負(fù)載,Cloud Spanner嘗試過在后臺(tái)根據(jù)讀寫負(fù)載的不同,添加和刪除分片,以及在分片大小越過設(shè)定的閾值后,創(chuàng)建新的分片,但是在頻繁插入的表格中,這種情況不會(huì)很快發(fā)生,以避免產(chǎn)生熱點(diǎn)。

除了單調(diào)增加或減少鍵外,這個(gè)問題還影響到由任意確定性的鍵索引的表–例如,事件日志表格中不斷增加的時(shí)間戳。時(shí)間戳鍵的表也更容易出現(xiàn)讀取熱點(diǎn),因?yàn)樵诖蠖鄶?shù)情況下,最近的時(shí)間戳行相較于其他行的訪問頻率更高。(閱讀《Cloud Spanner - 選擇正確的主鍵》,了解更多關(guān)于檢測(cè)和避免熱點(diǎn)問題的詳細(xì)信息)。

序列生成器問題

序列生成器的概念,或者說稀缺性,是一個(gè)需要進(jìn)一步探索的重要領(lǐng)域。傳統(tǒng)的垂直 RDBMS都有集成的序列生成器,在事務(wù)過程中從一個(gè)序列中創(chuàng)建新的整數(shù)鍵。Cloud Spanner 由于其分布式架構(gòu),無法做到這一點(diǎn),因?yàn)樵诓迦胄骆I時(shí),要么在分片的主要節(jié)點(diǎn)之間會(huì)出現(xiàn)競(jìng)爭(zhēng),要么在生成新鍵時(shí),表必須全局鎖,而這兩者都會(huì)降低性能。

一個(gè)可行的辦法是,鍵由應(yīng)用程序生成(例如,將下一個(gè)鍵值存儲(chǔ)在數(shù)據(jù)庫中的一個(gè)單獨(dú)的表格中,或者從表格中獲取當(dāng)前最大的鍵值)。然而,你會(huì)遇到同樣的性能問題??紤]到由于應(yīng)用程序也可能是分布式的,可能會(huì)有多個(gè)數(shù)據(jù)庫客戶端試圖同時(shí)插入一條記錄,根據(jù)新鍵的生成方式,可能會(huì)出現(xiàn)兩種結(jié)果:

如果在事務(wù)中執(zhí)行對(duì)現(xiàn)有鍵的 SELECT,一個(gè)試圖插入記錄的應(yīng)用程序?qū)嵗龝?huì)因?yàn)樾墟i定,而阻止所有其他試圖插入記錄的應(yīng)用程序?qū)嵗?/span>

如果現(xiàn)有鍵的 SELECT 是在事務(wù)之外執(zhí)行的,那么每個(gè)試圖插入記錄的應(yīng)用程序?qū)嵗g都會(huì)產(chǎn)生競(jìng)爭(zhēng)。其中一個(gè)會(huì)成功,而其他的實(shí)例在插入記錄失敗后必須重新嘗試(包括生成一個(gè)新鍵),因?yàn)檫@個(gè)鍵已經(jīng)存在了。

好的鍵是如何產(chǎn)生的?

那么,如果順序鍵會(huì)限制 Cloud Spanner 中的數(shù)據(jù)庫性能,那么應(yīng)該使用什么鍵呢?理想情況下,在選擇主鍵時(shí),主鍵的靠左的字段的數(shù)據(jù)應(yīng)該是均勻的、半隨機(jī)分布的。

生成這樣的鍵有一種簡(jiǎn)單方法,是使用隨機(jī)數(shù),例如隨機(jī)的通用唯一標(biāo)識(shí)碼(UUUID)。注意,UUUID 有好幾種。版本 1 和 2 使用確定性前綴,如時(shí)間戳或 MAC 地址等。確保你使用的 UUUID 生成方法是隨機(jī)分布的,即v4,至少在高階字節(jié)上是隨機(jī)分布的。這將確保鍵空間中的鍵均勻分布,從而讓負(fù)載均勻地分布在spanner節(jié)點(diǎn)上。

雖然另一種方法是使用一些現(xiàn)實(shí)世界中的數(shù)據(jù)屬性,這些屬性是不可變的,并且在鍵范圍內(nèi)均勻分布,但這是一個(gè)相當(dāng)大的挑戰(zhàn),因?yàn)榇蠖鄶?shù)均勻分布的屬性都是離散的,不是連續(xù)的。例如,擲骰子的隨機(jī)結(jié)果是均勻分布的,有六個(gè)有限值。而連續(xù)分布可以依靠一個(gè)無理數(shù),比如說π。

如果我真的需要一個(gè)整數(shù)序列作為鍵,怎么辦?

雖然這不是我們推薦的,但在某些情況下,整數(shù)序列鍵是必須的,無論是出于遺留問題還是外部原因,例如員工 ID。

要使用整數(shù)序列鍵,你首先需要一個(gè)在分布式系統(tǒng)中穩(wěn)定的序列生成器。其中一種方法是在 Cloud Spanner 中的表里,為每個(gè)要求的序列包含一個(gè)行,這個(gè)行又序列中的下一個(gè)值,因此它看起來類似這樣:

CREATE TABLE Sequences (

Sequence_ID STRING(MAX) NOT NULL, -- The name of the sequence

Next_Value INT64 NOT NULL

) PRIMARY KEY (Sequence_ID)

當(dāng)需要新 ID 值的時(shí)候,序列的下一個(gè)值會(huì)被讀取、遞增,并在插入新行的同一事務(wù)中更新。

注意,當(dāng)插入多行時(shí),這會(huì)降低性能,因?yàn)槲覀兩厦鎰?chuàng)建的序列表更新的時(shí)候,每次插入都會(huì)中斷其他插入。

這個(gè)性能問題可以解決----代價(jià)是序列中可能出現(xiàn)的斷檔----比如如果每個(gè)應(yīng)用程序?qū)嵗ㄟ^將 Next_Value 增加至 100,來一次性保存 100 個(gè)序列值,然后在塊內(nèi)部管理單個(gè)ID。

在使用序列的表中,不能簡(jiǎn)單地以數(shù)字序列值本身作為鍵,因?yàn)檫@將導(dǎo)致最后一個(gè)拆分值成為熱點(diǎn)(如前文所述)。因此,應(yīng)用程序必須生成一個(gè)復(fù)雜鍵,將行隨機(jī)分配到各分片之間。

這就是所謂的應(yīng)用級(jí)分片(application-level sharding),通過在主鍵中的序列ID前綴一個(gè)包含均勻分布的值的附加列來實(shí)現(xiàn),例如,原始ID的哈希值,或者是ID的位反轉(zhuǎn)。如下所示:

CREATE TABLE Table1 (

Hashed_Id INT64 NOT NULL,

ID INT64 NOT NULL,

-- other columns with data values follow....

) PRIMARY KEY (Hashed_Id, Id)

即使是一個(gè)簡(jiǎn)單的循環(huán)冗余校驗(yàn)(CRC)32校驗(yàn)和,也足以提供一個(gè)適當(dāng)?shù)膫坞S機(jī)Hashed_Id。它不一定必須是安全的,只要能打散順序編號(hào)鍵的行序就可以了,如下表所示。

ia_12100000003.png

注意,每次直接讀取一條記錄,都必須指定 ID 和 Hashed_Id,以防止全表掃描,參考下面這個(gè)例子:

SELECT * FROM Table1

WHERE t1.Hashed_Id = 0xDEADBEEF

AND t1.Id = 1234

同樣的,每當(dāng)這個(gè)表與查詢中的其他表通過 Id 連接時(shí),連接也必須同時(shí)使用ID和Hashed_Id。否則,你就要損失性能,因?yàn)樾枰M(jìn)行表掃描才能找到該行。這意味著引用 ID 的表必須同時(shí)包含 Hashed_Id,如下:

CREATE TABLE Table2 (

Id String(MAX),  -- UUID

Table1_Hashed_Id INT64 NOT NULL,

Table1_Id INT64 NOT NULL,

-- other columns with data values follow....

) PRIMARY KEY (Id)

SELECT * from Table2 t2 INNER JOIN Table1 t1

ON t1.Hashed_Id = t2.Table1_Hashed_Id

AND t1.Id = t2.Table1_Id

WHERE ... -- some criteria

如果我真的需要使用時(shí)間戳作為鍵,怎么辦?

很多情況下,用時(shí)間戳作為鍵的行也會(huì)指向其他表的一些數(shù)據(jù)。例如,一個(gè)銀行賬戶上的交易將指向源賬戶。在這種情況下,假設(shè)源賬戶已經(jīng)合理地平均分布了,你可以先用一個(gè)包含賬號(hào)的組合鍵,先賬號(hào),再時(shí)間戳。

CREATE TABLE Transactions (

account_number INT64 NOT NULL,

timestamp TIMESTAMP NOT NULL,

transaction_info ...,

) PRIMARY KEY (account_number, timestamp DESC)

分片將主要用到賬號(hào)而不是時(shí)間戳,從而將新添加的行分布在不同的分片中。

請(qǐng)注意,在這個(gè)表中,時(shí)間戳是按降序排列的。這是因?yàn)樵诖蠖鄶?shù)情況下,你想讀取最近的交易----這在表里排在最前邊----所以你不需要掃描整個(gè)表來找到最近的記錄。

如果你沒這么做,或者不能有外部引用,又或者有其他數(shù)據(jù)可以在鍵中使用,以分配順序,那么你就需要執(zhí)行應(yīng)用級(jí)分片,如前面講到的整數(shù)序列示例。

注意,簡(jiǎn)單哈希值會(huì)使按時(shí)間戳范圍進(jìn)行查詢的速度變得非常慢,因?yàn)闄z索一個(gè)時(shí)間戳范圍,需要進(jìn)行一次完整的表掃描,才能覆蓋所有的哈希值。相反,我們建議從時(shí)間戳中生成一個(gè) ShardId。如圖所示:

TimestampShardId = CRC32(Timestamp) % 100

然后會(huì)從時(shí)間戳中返回一個(gè) 0-99 之間的偽隨機(jī)值。你可以在表的主鍵中使用這個(gè)

ShardId,這樣就可以將順序時(shí)間戳分布在多個(gè)拆分中,類似這樣:

CREATE TABLE Events (

TimestampShardId INT64 NOT NULL

Timestamp TIMESTAMP NOT NULL,

event_info...

) PRIMARY KEY (TimestampShardId, Timestamp DESC)

例如,一個(gè)包含 2018 年前 10 天日期的表(如果沒有 ShardId 就會(huì)按日期順序存儲(chǔ)在表中),會(huì)給出如下排序:

ia_12100000004.png

進(jìn)行查詢時(shí),必須使用 BETWEEN 子句,以便能夠在不執(zhí)行表掃描的情況下,跨所有分片進(jìn)行選擇。

Select * from Events

WHERE

TimestampShardId BETWEEN 0 AND 99

AND Timestamp > @lower_bound

AND Timestamp < @upper_bound;

注意,ShardId 只是改進(jìn)鍵分布的一種方法,以便 Cloud Spanner 可以使用多個(gè)拆分來存儲(chǔ)順序時(shí)間戳。它并不能識(shí)別實(shí)際的數(shù)據(jù)庫拆分,不同表中具有相同的 ShardId 的行可能處于不同的分片中。

遷移的影響

當(dāng)你要從現(xiàn)有的 RDBMS 遷移到Cloud Spanner 時(shí),如果使用的鍵不適合 Cloud Spanner,請(qǐng)注意到上述事項(xiàng)。如有必要,請(qǐng)?jiān)诒碇刑砑渔I哈希值或更改鍵順序。

決定 Cloud Spanner 中的索引

在傳統(tǒng) RDBMS 中,通過非主鍵的值來查找表中的行,索引是非常有效的方法。在大多數(shù)情況下,通過索引進(jìn)行的行查詢與通過主鍵進(jìn)行的行查詢所需的時(shí)間大致相同。這是因?yàn)楸砗退饕怯蓡我还?jié)點(diǎn)管理的,所以索引可以直接指向表的磁盤行。

在 Cloud Spanner 中,索引實(shí)際上是用表來實(shí)現(xiàn)的,這使得索引可以分布式實(shí)現(xiàn),并且可以具有與普通表一樣的擴(kuò)展性和性能。

但是,由于這種類型的實(shí)現(xiàn),使用索引從表行讀取數(shù)據(jù)的效率,不如傳統(tǒng)RDBMS 的效率高。它實(shí)際上是與原始表的內(nèi)部連接,所以使用索引鍵從表中讀取數(shù)據(jù)就變成了這個(gè)過程:

查找分片中的索引鍵

從分片中讀取索引行,以獲得表鍵

查找分片中的表鍵

從分片中讀取表行,以獲得行值

返回行值

注意,不能保證索引鍵的拆分,和表鍵的分片位于同一個(gè)節(jié)點(diǎn)上,所以一個(gè)簡(jiǎn)單的索引查詢,可能就需要跨節(jié)點(diǎn)通信去讀取一行。

同樣,更新一個(gè)有索引的表,很可能需要多節(jié)點(diǎn)寫入,來更新表行和索引行。因此,在 Cloud Spanner 中使用索引,總需要在提高讀取性能和降低寫入性能之間進(jìn)行權(quán)衡。

索引鍵和熱點(diǎn)

由于索引在 Cloud Spanner 中是以表的形式呈現(xiàn)的,因此你會(huì)遇到與表鍵相同的問題。即使底層表使用的是分布良好的主鍵,但如果在具有較差的值(如時(shí)間戳)的列上建立索引,也會(huì)導(dǎo)致創(chuàng)建一個(gè)熱點(diǎn)。這是因?yàn)楫?dāng)行被插入到表上時(shí),索引也會(huì)插入新的行,而對(duì)這些新行的寫入,總會(huì)被發(fā)送到同一個(gè)分片。

因此,在創(chuàng)建索引時(shí)必須小心謹(jǐn)慎,我們建議你只使用具有良好分布值的列來創(chuàng)建索引,就像選擇表的主鍵時(shí)一樣。

在某些情況下,您需要對(duì)索引列進(jìn)行應(yīng)用級(jí)分片,以便創(chuàng)建一個(gè)合成的ShardId 列,該列可以在索引中使用,從而在分片上分配值。

例如,下面的這個(gè)配置會(huì)在因索引插入事件時(shí),創(chuàng)建一個(gè)熱點(diǎn),即使 UserId是隨機(jī)分布的。

CREATE TABLE Events (

UserId String(MAX),

Timestamp TIMESTAMP,

EventData)

PRIMARY KEY (UserId, Timestamp DESC);

CREATE INDEX EventsByTimestamp ON Events (Timestamp DESC);

與僅以時(shí)間戳為鍵的表一樣,需要在表中添加一個(gè)合成的 ShardId 列,然后作為第一個(gè)索引列,以幫助索引在各拆分之間分布。

如下是一個(gè)簡(jiǎn)單的 ShardId 生成器:

TimestampShardId = CRC32(Timestamp) % 100

這會(huì)輸出一個(gè)哈希值在 0-99 之間時(shí)間戳。你需要把它作為新列添加到原始表中,然后用它作為索引鍵的第一個(gè)字段鍵,類似這樣:

CREATE TABLE Events (

UserId String(MAX),

Timestamp TIMESTAMP,

TimestampShardId INT64,

EventData)

PRIMARY KEY (UserId, Timestamp DESC);

CREATE INDEX EventsByTimestamp ON Events (TimestampShardId,Timestamp);

這將去掉索引更新時(shí)的熱點(diǎn),但會(huì)降低時(shí)間戳范圍查詢的速度,因?yàn)槟惚仨殲槊總€(gè) ShardId值(0-99)運(yùn)行查詢,以獲得所有分片的時(shí)間戳范圍:

Select * from Events@{FORCE_INDEX=EventsByTimestamp}

WHERE

TimestampShardId BETWEEN 0 AND 99

AND Timestamp > @lower_bound

AND Timestamp < @upper_bound;

使用這種類型的索引和分片策略,必須在讀取時(shí)的額外復(fù)雜性,和索引性能的提高之間,做取舍。

你應(yīng)該知道的其他索引

當(dāng)你遷移到 Cloud Spanner 后,你還需要了解這些索引的功能,以及什么時(shí)候使用它們。

When you’re migrating to Cloud Spanner, you’ll also want to understand how these other index types function and when you might need to use them:

NULL_FILTERED 索引

默認(rèn)情況下,Cloud Spanner 將使用 NULL 索引列值對(duì)行進(jìn)行索引。NULL 被認(rèn)為是盡可能小的值,因此這些值將出現(xiàn)在索引的開頭。

也可以通過使用 CREATE NULL_FILTERED INDEX 語法創(chuàng)建一個(gè)索引,這個(gè)索引會(huì)忽略NULL 索引列值的行。

這個(gè)索引會(huì)比完整的索引小,因?yàn)樗鼘⒂行У爻蔀楸砩系木唧w化過濾視圖,當(dāng)需要進(jìn)行表掃描時(shí),查詢速度將比完整的表更快。

UNIQUE索引

你可以使用一個(gè) UNIQUE 索引,強(qiáng)制讓表的一個(gè)列具有唯一值。這個(gè)約束將在事務(wù)提交時(shí)(和索引創(chuàng)建時(shí))應(yīng)用。

覆蓋索引和 STORING 子句

為了優(yōu)化索引讀取的性能,Cloud Spanner 可以將表行的列值存儲(chǔ)在索引中,從而無需讀取表。這被稱為覆蓋索引。這可以通過定義索引時(shí)使用 STORING 子句來實(shí)現(xiàn)。然后可以直接從索引中讀取列的值,所以從索引中讀取的效果和從表中讀取的效果一樣好。例如,這個(gè)表包含了員工數(shù)據(jù)。

CREATE TABLE Employees (

CompanyUUID INT64,

EmployeeUUID INT64,

FullName STRING(MAX)

...

) PRIMARY KEY (CompanyUUID,EmployeeUUID)

如果你經(jīng)常需要查詢員工的全名,例如,你可以在雇員 UUID 上創(chuàng)建一個(gè)索引,存儲(chǔ)全名,以便快速查詢:

CREATE INDEX EmployeesById

ON Employees (EmployeeUUID)

STORING (FullName);

強(qiáng)制使用索引

Cloud Spanner 的查詢引擎只有在極少數(shù)情況下才會(huì)自動(dòng)使用索引(當(dāng)查詢完全被索引覆蓋時(shí)),所以在 SQL SELECT 語法中使用 FORCE_INDEX 指令來確保 Cloud Spanner 從索引中查找值很重要。你可以在文檔中找到更多介紹)。

Select *

from  Employees@{FORCE_INDEX=EmployeesById}

Where EmployeeUUID=xxx;

注意,使用 Cloud Spanner 讀取 API(Read API)時(shí),你只能執(zhí)行完全覆蓋的查詢,即索引存儲(chǔ)所有請(qǐng)求列的查詢。要使用索引從原始表讀取列,必須使用 SQL 查詢。有關(guān)示例,請(qǐng)參閱入門文檔中的「使用二級(jí)索引 」部分。

繼續(xù)學(xué)習(xí) Cloud Spanner

當(dāng)你使用 Cloud Spanner 這樣的基于云構(gòu)建、橫向擴(kuò)展的數(shù)據(jù)庫時(shí),會(huì)發(fā)現(xiàn)與你多年來一直使用的 RDBMS 相比,概念差異很大。一旦你熟悉了鍵和索引的工作原理,你就可以開始利用 Cloud Spanner 的優(yōu)勢(shì)來實(shí)現(xiàn)更快的可擴(kuò)展性。

在本系列的下一篇文章中,我們將探討如何處理以前通過觸發(fā)器和存儲(chǔ)過程,來實(shí)現(xiàn)的業(yè)務(wù)邏輯,而 Cloud Spanner 并不支持這兩種方式。

立即登錄,閱讀全文
版權(quán)說明:
本文內(nèi)容來自于Google Cloud,本站不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。文章內(nèi)容系作者個(gè)人觀點(diǎn),不代表快出海對(duì)觀點(diǎn)贊同或支持。如有侵權(quán),請(qǐng)聯(lián)系管理員(zzx@kchuhai.com)刪除!
相關(guān)文章
進(jìn)軍高增長(zhǎng)市場(chǎng),公司繼續(xù)保持兩位數(shù)增長(zhǎng),谷歌為何應(yīng)該逢低買入?
進(jìn)軍高增長(zhǎng)市場(chǎng),公司繼續(xù)保持兩位數(shù)增長(zhǎng),谷歌為何應(yīng)該逢低買入?
出色的財(cái)務(wù)表現(xiàn)是其堅(jiān)實(shí)基本面的一大亮點(diǎn)。
Google Cloud
投融資
2025-01-222025-01-22
新版GKE可管理最多6.5萬集群節(jié)點(diǎn),超越AWS、Azure 10倍
新版GKE可管理最多6.5萬集群節(jié)點(diǎn),超越AWS、Azure 10倍
Google Cloud公布最新Google Kubernetes Engine版本,號(hào)稱可支持最高達(dá)65,000個(gè)節(jié)點(diǎn)的服務(wù)器集群,以執(zhí)行超大型AI模型。
Google Cloud
云服務(wù)
云計(jì)算
2024-11-152024-11-15
Google Cloud細(xì)說AI變現(xiàn)途徑:用戶一年暴增10倍
Google Cloud細(xì)說AI變現(xiàn)途徑:用戶一年暴增10倍
Google云計(jì)算平臺(tái)(Google Cloud)首席執(zhí)行官Thomas Kurian在高盛舉行的會(huì)議上,說明了該公司究竟是通過哪些途徑將AI變現(xiàn)。
Google Cloud
谷歌云
云計(jì)算
2024-09-132024-09-13
云計(jì)算平臺(tái)GCP的服務(wù)存在權(quán)限提升漏洞,未經(jīng)授權(quán)的攻擊者可借此訪問敏感數(shù)據(jù)
云計(jì)算平臺(tái)GCP的服務(wù)存在權(quán)限提升漏洞,未經(jīng)授權(quán)的攻擊者可借此訪問敏感數(shù)據(jù)
7月24日安全企業(yè)Tenable披露影響Google Cloud Platform(GCP)的權(quán)限提升漏洞ConfusedFunction,這項(xiàng)弱點(diǎn)發(fā)生在名為Cloud Functions的無服務(wù)器運(yùn)算服務(wù),以及稱作Cloud Build的CICD渠道服務(wù)。
Google Cloud
谷歌云
云計(jì)算
2024-07-272024-07-27
優(yōu)質(zhì)服務(wù)商推薦
更多
掃碼登錄
打開掃一掃, 關(guān)注公眾號(hào)后即可登錄/注冊(cè)
加載中
二維碼已失效 請(qǐng)重試
刷新
賬號(hào)登錄/注冊(cè)
個(gè)人VIP
小程序
快出海小程序
公眾號(hào)
快出海公眾號(hào)
商務(wù)合作
商務(wù)合作
投稿采訪
投稿采訪
出海管家
出海管家