实验设置说明和要求
保护您的账号和进度。请务必在无痕浏览器窗口中,使用实验凭证运行此实验。

Cloud Spanner - 定义架构并了解查询计划

实验 1 小时 30 分钟 universal_currency_alt 1 个点数 show_chart 入门级
info 此实验可能会提供 AI 工具来支持您学习。
此内容尚未针对移动设备进行优化。
为获得最佳体验,请在桌面设备上访问通过电子邮件发送的链接。

GSP1050

Google Cloud 自学实验的徽标

概览

Cloud Spanner 是 Google 的全托管式、可横向扩缩关系型数据库服务。金融服务、游戏、零售及众多其他行业的客户都信赖该服务,依托其运行自身要求最严苛的工作负载。在此类场景下进行大规模部署时,服务的一致性和可用性都至关重要。

在本实验中,您将回顾与架构相关的 Cloud Spanner 功能,并将这些功能应用于银行业务数据库。您还将回顾 Cloud Spanner 创建查询计划时所遵循的方法和规则。

您将执行的操作

在本实验中,您将学习修改 Cloud Spanner 实例的架构相关属性。

  • 将数据加载到表中
  • 使用预定义的 Python 客户端库代码来加载数据
  • 使用客户端库查询数据
  • 更新数据库架构
  • 添加二级索引
  • 审视查询计划

设置和要求

点击“开始实验”按钮前的注意事项

请阅读以下说明。实验是计时的,并且您无法暂停实验。计时器在您点击开始实验后即开始计时,显示 Google Cloud 资源可供您使用多长时间。

此实操实验可让您在真实的云环境中开展实验活动,免受模拟或演示环境的局限。为此,我们会向您提供新的临时凭据,您可以在该实验的规定时间内通过此凭据登录和访问 Google Cloud。

为完成此实验,您需要:

  • 能够使用标准的互联网浏览器(建议使用 Chrome 浏览器)。
注意:请使用无痕模式(推荐)或无痕浏览器窗口运行此实验。这可以避免您的个人账号与学生账号之间发生冲突,这种冲突可能导致您的个人账号产生额外费用。
  • 完成实验的时间 - 请注意,实验开始后无法暂停。
注意:请仅使用学生账号完成本实验。如果您使用其他 Google Cloud 账号,则可能会向该账号收取费用。

如何开始实验并登录 Google Cloud 控制台

  1. 点击开始实验按钮。如果该实验需要付费,系统会打开一个对话框供您选择支付方式。左侧是“实验详细信息”窗格,其中包含以下各项:

    • “打开 Google Cloud 控制台”按钮
    • 剩余时间
    • 进行该实验时必须使用的临时凭据
    • 帮助您逐步完成本实验所需的其他信息(如果需要)
  2. 点击打开 Google Cloud 控制台(如果您使用的是 Chrome 浏览器,请右键点击并选择在无痕式窗口中打开链接)。

    该实验会启动资源并打开另一个标签页,显示“登录”页面。

    提示:将这些标签页安排在不同的窗口中,并排显示。

    注意:如果您看见选择账号对话框,请点击使用其他账号
  3. 如有必要,请复制下方的用户名,然后将其粘贴到登录对话框中。

    {{{user_0.username | "<用户名>"}}}

    您也可以在“实验详细信息”窗格中找到“用户名”。

  4. 点击下一步

  5. 复制下面的密码,然后将其粘贴到欢迎对话框中。

    {{{user_0.password | "<密码>"}}}

    您也可以在“实验详细信息”窗格中找到“密码”。

  6. 点击下一步

    重要提示:您必须使用实验提供的凭据。请勿使用您的 Google Cloud 账号凭据。 注意:在本实验中使用您自己的 Google Cloud 账号可能会产生额外费用。
  7. 继续在后续页面中点击以完成相应操作:

    • 接受条款及条件。
    • 由于这是临时账号,请勿添加账号恢复选项或双重验证。
    • 请勿注册免费试用。

片刻之后,系统会在此标签页中打开 Google Cloud 控制台。

注意:如需访问 Google Cloud 产品和服务,请点击导航菜单,或在搜索字段中输入服务或产品的名称。 “导航菜单”图标和“搜索”字段

激活 Cloud Shell

Cloud Shell 是一种装有开发者工具的虚拟机。它提供了一个永久性的 5GB 主目录,并且在 Google Cloud 上运行。Cloud Shell 提供可用于访问您的 Google Cloud 资源的命令行工具。

  1. 点击 Google Cloud 控制台顶部的激活 Cloud Shell “激活 Cloud Shell”图标

  2. 在弹出的窗口中执行以下操作:

    • 继续完成 Cloud Shell 信息窗口中的设置。
    • 授权 Cloud Shell 使用您的凭据进行 Google Cloud API 调用。

如果您连接成功,即表示您已通过身份验证,且项目 ID 会被设为您的 Project_ID 。输出内容中有一行说明了此会话的 Project_ID

Your Cloud Platform project in this session is set to {{{project_0.project_id | "PROJECT_ID"}}}

gcloud 是 Google Cloud 的命令行工具。它已预先安装在 Cloud Shell 上,且支持 Tab 自动补全功能。

  1. (可选)您可以通过此命令列出活跃账号名称:
gcloud auth list
  1. 点击授权

输出:

ACTIVE: * ACCOUNT: {{{user_0.username | "ACCOUNT"}}} To set the active account, run: $ gcloud config set account `ACCOUNT`
  1. (可选)您可以通过此命令列出项目 ID:
gcloud config list project

输出:

[core] project = {{{project_0.project_id | "PROJECT_ID"}}} 注意:如需查看在 Google Cloud 中使用 gcloud 的完整文档,请参阅 gcloud CLI 概览指南

Cloud Spanner 实例

为让您能够更快完成本实验,已为您自动创建 Cloud Spanner 实例、数据库和表。

以下是一些详细信息,供您参考:

名称 详细信息
Cloud Spanner 实例 banking-ops-instance 这是项目级实例
Cloud Spanner 数据库 banking-ops-db 这是实例专属数据库
Portfolio 包含顶级银行产品/服务
Category 包含第二级银行产品/服务分组
Product 包含具体的银行产品/服务明细项
Campaigns 包含营销计划的详细信息

任务 1. 将数据加载到表中

所创建的 banking-ops-db 包含空表。请按照以下步骤,将数据加载到 PortfolioCategoryProduct 三个表中。

  1. 在 Cloud 控制台中,打开导航菜单 (console_nav_small.png) > 查看所有产品,然后在数据库下点击 Spanner

  2. 实例名称为 banking-ops-instance,请点击该名称以探究数据库。

  3. 关联的数据库名为 banking-ops-db。点击该名称,向下滚动到,您会看到已有四个表。

  4. 在控制台的左侧窗格中,点击 Spanner Studio。然后,点击右侧框架中的 + 新建 SQL 编辑器标签页按钮。

  5. 您将来到查询页面。将下面的 INSERT 语句作为一个整体代码块进行粘贴,以便为 Portfolio 表加载数据。Spanner 将依次执行每个语句。点击运行

insert into Portfolio (PortfolioId, Name, ShortName, PortfolioInfo) values (1, "Banking", "Bnkg", "All Banking Business"); insert into Portfolio (PortfolioId, Name, ShortName, PortfolioInfo) values (2, "Asset Growth", "AsstGrwth", "All Asset Focused Products"); insert into Portfolio (PortfolioId, Name, ShortName, PortfolioInfo) values (3, "Insurance", "Ins", "All Insurance Focused Products");
  1. 屏幕下半部分会显示逐行插入数据的结果。每一行插入数据还会分别显示一个绿色对勾标记。Portfolio 表现在有三行数据。

  2. 点击页面顶部的清除

  3. 将下面的 INSERT 语句作为一个整体代码块进行粘贴,以便为 Category 表加载数据。点击运行

insert into Category (CategoryId,PortfolioId,CategoryName) values (1,1,"Cash"); insert into Category (CategoryId,PortfolioId,CategoryName) values (2,2,"Investments - Short Return"); insert into Category (CategoryId,PortfolioId,CategoryName) values (3,2,"Annuities"); insert into Category (CategoryId,PortfolioId,CategoryName) values (4,3,"Life Insurance");
  1. 屏幕下半部分会显示逐行插入数据的结果。每一行插入数据还会分别显示一个绿色对勾标记。Category 表现在有四行数据。

  2. 点击页面顶部的清除

  3. 将下面的 INSERT 语句作为一个整体代码块进行粘贴,以便为 Product 表加载数据。点击运行

insert into Product (ProductId,CategoryId,PortfolioId,ProductName,ProductAssetCode,ProductClass) values (1,1,1,"Checking Account","ChkAcct","Banking LOB"); insert into Product (ProductId,CategoryId,PortfolioId,ProductName,ProductAssetCode,ProductClass) values (2,2,2,"Mutual Fund Consumer Goods","MFundCG","Investment LOB"); insert into Product (ProductId,CategoryId,PortfolioId,ProductName,ProductAssetCode,ProductClass) values (3,3,2,"Annuity Early Retirement","AnnuFixed","Investment LOB"); insert into Product (ProductId,CategoryId,PortfolioId,ProductName,ProductAssetCode,ProductClass) values (4,4,3,"Term Life Insurance","TermLife","Insurance LOB"); insert into Product (ProductId,CategoryId,PortfolioId,ProductName,ProductAssetCode,ProductClass) values (5,1,1,"Savings Account","SavAcct","Banking LOB"); insert into Product (ProductId,CategoryId,PortfolioId,ProductName,ProductAssetCode,ProductClass) values (6,1,1,"Personal Loan","PersLn","Banking LOB"); insert into Product (ProductId,CategoryId,PortfolioId,ProductName,ProductAssetCode,ProductClass) values (7,1,1,"Auto Loan","AutLn","Banking LOB"); insert into Product (ProductId,CategoryId,PortfolioId,ProductName,ProductAssetCode,ProductClass) values (8,4,3,"Permanent Life Insurance","PermLife","Insurance LOB"); insert into Product (ProductId,CategoryId,PortfolioId,ProductName,ProductAssetCode,ProductClass) values (9,2,2,"US Savings Bonds","USSavBond","Investment LOB");
  1. 屏幕下半部分会显示逐行插入数据的结果。每一行插入数据还会分别显示一个绿色对勾标记。Product 表现在有九行数据。

  2. 点击检查我的进度以验证是否完成了以下目标:

将数据加载到 Portfolio、Category 和 Product 表中

任务 2. 使用预构建的 Python 客户端库代码来加载数据

在接下来的几个步骤中,您将使用以 Python 编写的客户端库。

  1. 打开 Cloud Shell,粘贴以下命令以创建新目录并切换到该目录,以便存放所需的文件。
mkdir python-helper cd python-helper
  1. 接下来,下载两个文件。其中一个文件用于设置环境。另一个文件是实验代码。
wget https://storage.googleapis.com/cloud-training/OCBL373/requirements.txt wget https://storage.googleapis.com/cloud-training/OCBL373/snippets.py
  1. 创建一个隔离的 Python 环境,并安装 Cloud Spanner 客户端的依赖项。
pip install -r requirements.txt pip install setuptools
  1. snippets.py 是一个包含多个 Cloud Spanner DDL、DML 和 DCL 函数的合并文件,您将在本实验中将其用作辅助工具。使用 insert_data 参数执行 snippets.py,以便填充 Campaigns 表。
python snippets.py banking-ops-instance --database-id banking-ops-db insert_data
  1. 点击检查我的进度以验证是否完成了以下目标:
将数据加载到 Campaigns 表中

任务 3. 使用客户端库查询数据

snippets.py 中的 query_data() 函数可用于查询数据库。在本例中,您将使用它来确认数据已加载到 Campaigns 表中。请勿更改任何代码,此处显示了该部分供您参考。

def query_data(instance_id, database_id): """Queries sample data from the database using SQL.""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) with database.snapshot() as snapshot: results = snapshot.execute_sql( "SELECT CampaignId,PortfolioId,CampaignStartDate,CampaignEndDate,CampaignName,CampaignBudget FROM Campaigns" ) for row in results: print(u"CampaignId: {}, PortfolioId: {}, CampaignStartDate: {}, CampaignEndDate: {}, CampaignName: {}, CampaignBudget: {}".format(*row))
  1. 使用 query_data 参数执行 snippets.py,以便查询 Campaigns 表。
python snippets.py banking-ops-instance --database-id banking-ops-db query_data

结果应如下所示

CampaignId: 1, PortfolioId: 1, CampaignStartDate: 2022-06-07, CampaignEndDate: 2022-06-07, CampaignName: New Account Reward, CampaignBudget: 15000 CampaignId: 2, PortfolioId: 2, CampaignStartDate: 2022-06-07, CampaignEndDate: 2022-06-07, CampaignName: Intro to Investments, CampaignBudget: 5000 CampaignId: 3, PortfolioId: 2, CampaignStartDate: 2022-06-07, CampaignEndDate: 2022-06-07, CampaignName: Youth Checking Accounts, CampaignBudget: 25000 CampaignId: 4, PortfolioId: 3, CampaignStartDate: 2022-06-07, CampaignEndDate: 2022-06-07, CampaignName: Protect Your Family, CampaignBudget: 10000

任务 4. 更新数据库架构

作为数据库管理员 (DBA),职责要求您向 Category 表添加一个名为 MarketingBudget 的新列。向现有表添加新列需要更新数据库架构。Cloud Spanner 支持在数据库继续处理流量的同时,对数据库进行架构更新。架构更新不需要使数据库离线,也不会锁定整个表或列;在架构更新期间,您可以继续对数据库进行数据读写操作。

使用 Python 添加列

Database 类的 update_ddl() 方法用于修改架构。

请使用 snippets.py 中的 add_column() 函数,该函数实现了上述方法。请勿更改任何代码,此处显示了该部分供您参考。

def add_column(instance_id, database_id): """Adds a new column to the Albums table in the example database.""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) operation = database.update_ddl( ["ALTER TABLE Category ADD COLUMN MarketingBudget INT64"] ) print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) print("Added the MarketingBudget column.")
  1. 使用 add_column 参数执行 snippets.py
python snippets.py banking-ops-instance --database-id banking-ops-db add_column
  1. 点击检查我的进度以验证是否完成了以下目标:
向 Category 表中添加列

向现有表中添加列的其他可选方法包括:

通过 gcloud CLI 发出 DDL 命令。

注意:此方法仅作为备选示例展示。请勿发出此命令。

下面的代码示例同样会完成您刚才通过 Python 执行的任务。

gcloud spanner databases ddl update banking-ops-db --instance=banking-ops-instance --ddl='ALTER TABLE Category ADD COLUMN MarketingBudget INT64;'

在 Cloud 控制台中发出 DDL 命令。

注意:此方法仅作为备选示例展示。请勿执行此操作。
  1. 点击数据库列表中的表名称。
  2. 点击页面右上角的编写 DDL
  3. 将相应的 DDL 粘贴到 DDL 模板框中。
  4. 点击提交

AddColumnUI.png

将数据写入新列

以下代码可将数据写入新列。对于 CategoryId 为 1 且 PortfolioId 为 1 的行,它会将 MarketingBudget 设置为 100000;对于 CategoryId 为 3 且 PortfolioId 为 2 的行,则设置为 500000。请勿更改任何代码,此处显示了该部分供您参考。

def update_data(instance_id, database_id): """Updates sample data in the database. This updates the `MarketingBudget` column which must be created before running this sample. You can add the column by running the `add_column` sample or by running this DDL statement against your database """ spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) with database.batch() as batch: batch.update( table="Category", columns=("CategoryId", "PortfolioId", "MarketingBudget"), values=[(1, 1, 100000), (3, 2, 500000)], ) print("Updated data.")
  1. 使用 update_data 参数执行 snippets.py
python snippets.py banking-ops-instance --database-id banking-ops-db update_data
  1. 再次查询该表,查看更新结果。使用 query_data_with_new_column 参数执行 snippets.py
python snippets.py banking-ops-instance --database-id banking-ops-db query_data_with_new_column

结果应为:

CategoryId: 1, PortfolioId: 1, MarketingBudget: 100000 CategoryId: 2, PortfolioId: 2, MarketingBudget: None CategoryId: 3, PortfolioId: 2, MarketingBudget: 500000 CategoryId: 4, PortfolioId: 3, MarketingBudget: None

任务 5. 添加二级索引

假设您想要提取 Categories 表中 CategoryNames 值处于某一范围内的所有行。您可以使用 SQL 语句或读取调用,来读取 CategoryName 列中的所有值,然后舍弃不符合条件的行。不过,执行这种全表扫描开销很大,对包含大量行的表来说更是如此。相反,如果对表创建二级索引,按非主键列进行搜索,则可以提高行检索速度。

向现有表中添加二级索引需要更新架构。与其他架构更新一样,Cloud Spanner 支持在数据库继续处理流量的同时添加索引。Cloud Spanner 会在后台使用数据来填充索引(也称为“回填”)。回填可能需要几分钟才能完成,但在此过程中,您无需使数据库离线,也无需避免向某些表或列执行写操作。

使用 Python 客户端库添加二级索引

使用 add_index() 方法创建二级索引。请勿更改任何代码,此处显示了该部分供您参考。

def add_index(instance_id, database_id): """Adds a simple index to the example database.""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) operation = database.update_ddl( ["CREATE INDEX CategoryByCategoryName ON Category(CategoryName)"] ) print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) print("Added the CategoryByCategoryName index.")
  1. 使用 add_index 参数执行 snippets.py
python snippets.py banking-ops-instance --database-id banking-ops-db add_index
  1. 点击检查我的进度以验证是否完成了以下目标:
向 Category 表中添加二级索引

使用索引读取数据

如需使用索引来读取数据,请调用包含索引参数的 read() 方法的变体。请勿更改任何代码,此处显示了该部分供您参考。

def read_data_with_index(instance_id, database_id): """Reads sample data from the database using an index. """ spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) with database.snapshot() as snapshot: keyset = spanner.KeySet(all_=True) results = snapshot.read( table="Category", columns=("CategoryId", "CategoryName"), keyset=keyset, index="CategoryByCategoryName", ) for row in results: print("CategoryId: {}, CategoryName: {}".format(*row))
  1. 使用 read_data_with_index 参数执行 snippets.py
python snippets.py banking-ops-instance --database-id banking-ops-db read_data_with_index

结果应如下所示:

CategoryId: 3, CategoryName: Annuities CategoryId: 1, CategoryName: Cash CategoryId: 2, CategoryName: Investments - Short Return CategoryId: 4, CategoryName: Life Insurance

添加带 STORING 子句的索引

您可能已经注意到,上面的读取示例没有包含读取 MarketingBudget 列。这是因为,Cloud Spanner 的读取接口不支持将索引与数据表联接起来,以查找未存储在索引中的值。

为了绕过此限制,请创建 CategoryByCategoryName 索引的备选定义,在索引中存储 MarketingBudget 的副本。

使用 Database 类的 update_ddl() 方法,添加带 STORING 子句的索引。请勿更改任何代码,此处显示了该部分供您参考。

def add_storing_index(instance_id, database_id): """Adds an storing index to the example database.""" spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) operation = database.update_ddl( [ "CREATE INDEX CategoryByCategoryName2 ON Category(CategoryName)" "STORING (MarketingBudget)" ] ) print("Waiting for operation to complete...") operation.result(OPERATION_TIMEOUT_SECONDS) print("Added the CategoryByCategoryName2 index.")
  1. 使用 add_storing_index 参数执行 snippets.py
python snippets.py banking-ops-instance --database-id banking-ops-db add_storing_index

现在,您可以在使用 CategoryByCategoryName2 索引的同时,执行读取操作来提取 CategoryIdCategoryNameMarketingBudget 列中的数据。请勿更改任何代码,此处显示了该部分供您参考。

def read_data_with_storing_index(instance_id, database_id): """Reads sample data from the database using an index with a storing clause. """ spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) database = instance.database(database_id) with database.snapshot() as snapshot: keyset = spanner.KeySet(all_=True) results = snapshot.read( table="Category", columns=("CategoryId", "CategoryName", "MarketingBudget"), keyset=keyset, index="CategoryByCategoryName2", ) for row in results: print(u"CategoryNameId: {}, CategoryName: {}, " "MarketingBudget: {}".format(*row))
  1. 使用 read_data_with_storing_index 参数执行 snippets.py
python snippets.py banking-ops-instance --database-id banking-ops-db read_data_with_storing_index

结果应为

CategoryNameId: 3, CategoryName: Annuities, MarketingBudget: 500000 CategoryNameId: 1, CategoryName: Cash, MarketingBudget: 100000 CategoryNameId: 2, CategoryName: Investments - Short Return, MarketingBudget: None CategoryNameId: 4, CategoryName: Life Insurance, MarketingBudget: None

任务 6. 审视查询计划

在本部分,您将探索 Cloud Spanner 查询计划

  1. 返回 Cloud 控制台,它应该仍然位于 Spanner Studio查询标签页上。清除所有现有查询,粘贴并运行以下查询:
SELECT Name, ShortName, CategoryName FROM Portfolio INNER JOIN Category ON Portfolio.PortfolioId = Category.PortfolioId;
  1. 结果应如下所示:

PlanQuery.png

查询的生命周期

Cloud Spanner 中的 SQL 查询首先被编译为执行计划,然后发送到初始根服务器进行执行。之所以选择根服务器,是为了最大限度减少到达所查询的数据而经历的跃点数。根服务器然后执行以下操作:

  • 启动子计划的远程执行(如有必要)
  • 等待远程执行的结果
  • 处理剩余的本地执行步骤,例如聚合结果
  • 返回查询的结果

接收子计划的远程服务器充当其子计划的“根”服务器,遵循与最顶层根服务器相同的模式。其结果是一个远程执行树。从概念上讲,查询执行从上到下进行,而查询结果自下而上返回。以下图表展示了这种模式:

SPNPlan.png

聚合查询

现在来看一下聚合查询的查询计划。

  1. Spanner Studio查询标签页中,清除现有查询,粘贴并运行以下查询。
SELECT pr.ProductId, COUNT(*) AS ProductCount FROM Product AS pr WHERE pr.ProductId < 100 GROUP BY pr.ProductId;
  1. 查询完成后,点击查询主体下方的解释标签页,审视查询计划。

Cloud Spanner 会将执行计划发送到根服务器,该服务器将负责协调查询的执行并执行子计划的远程分发。

此执行计划首先进行序列化,对所有返回的值进行排序。然后,该计划会完成初始哈希聚合操作符的执行,以初步计算结果。接下来执行分布式联合,将子计划分发给那些数据分块满足 ProductId < 100 条件的远程服务器。分布式联合会将结果发送给最终哈希聚合操作符。该聚合操作符会按 ProductId 执行 COUNT 聚合,并将结果返回给序列化结果操作符。最后执行扫描,对要返回的结果进行排序。

结果应如下所示:

SPNAggPlan.png

提示:如需了解查询计划中每个步骤的更多详细信息,请点击任意操作符,屏幕右侧将相应地发生变化。

SPNPlanDetail.png

同位联接查询

交错表以物理方式进行存储,会将相关表的行共同放置在一处。交错表之间的联接称为同位联接。与需要索引的联接或回表联接相比,同位联接具备性能优势。

  1. Spanner Studio查询标签页中,清除现有查询,粘贴并运行以下查询。
SELECT c.CategoryName, pr.ProductName FROM Category AS c, Product AS pr WHERE c.PortfolioId = pr.PortfolioId AND c.CategoryId = pr.CategoryId;
  1. 查询完成后,点击查询主体下方的解释标签页,审视查询计划。

此执行计划首先执行分布式联合,将子计划分发到具有 Category 表数据分块的远程服务器。由于 ProductCategory 的交错表,因此每台远程服务器都可以执行整个子计划,而无需联接其他服务器。

子计划包含交叉应用操作。每一次交叉应用操作都会对 Category 表执行表扫描,以检索 PortfolioIdCategoryIdCategoryName。然后,交叉应用操作会将表扫描的输出,映射到对 CategoryByCategoryName 索引执行的索引扫描输出,所遵循的过滤条件是索引中的 PortfolioId 与表扫描输出中的 PortfolioId 相匹配。每一次交叉应用操作都会将其结果发送给序列化结果操作符,该操作符会将 CategoryNameProductName 数据序列化,并将结果返回给局部分布式联合。分布式联合会聚合来自局部分布式联合的结果,并将其作为查询结果返回。

SPNColocated.png

恭喜!

现在,您已经对 Cloud Spanner 的架构相关功能以及 Spanner 创建查询计划的方法有了扎实的理解。

Google Cloud 培训和认证

…可帮助您充分利用 Google Cloud 技术。我们的课程会讲解各项技能与最佳实践,可帮助您迅速上手使用并继续学习更深入的知识。我们提供从基础到高级的全方位培训,并有点播、直播和虚拟三种方式选择,让您可以按照自己的日程安排学习时间。各项认证可以帮助您核实并证明您在 Google Cloud 技术方面的技能与专业知识。

上次更新手册的时间:2024 年 10 月 14 日

上次测试实验的时间:2024 年 10 月 14 日

版权所有 2026 Google LLC 保留所有权利。Google 和 Google 徽标是 Google LLC 的商标。其他所有公司名和产品名可能是其各自相关公司的商标。

准备工作

  1. 实验会创建一个 Google Cloud 项目和一些资源,供您使用限定的一段时间
  2. 实验有时间限制,并且没有暂停功能。如果您中途结束实验,则必须重新开始。
  3. 在屏幕左上角,点击开始实验即可开始

使用无痕浏览模式

  1. 复制系统为实验提供的用户名密码
  2. 在无痕浏览模式下,点击打开控制台

登录控制台

  1. 使用您的实验凭证登录。使用其他凭证可能会导致错误或产生费用。
  2. 接受条款,并跳过恢复资源页面
  3. 除非您已完成此实验或想要重新开始,否则请勿点击结束实验,因为点击后系统会清除您的工作并移除该项目

此内容目前不可用

一旦可用,我们会通过电子邮件告知您

太好了!

一旦可用,我们会通过电子邮件告知您

一次一个实验

确认结束所有现有实验并开始此实验

使用无痕浏览模式运行实验

请使用无痕模式或无痕式浏览器窗口运行此实验。这可以避免您的个人账号与学生账号之间发生冲突,这种冲突可能导致您的个人账号产生额外费用。