使用 SQL 查询查找数据时,Spanner 会自动使用可能有助于更高效地检索数据的任何二级索引。但在少数情况下,Spanner 可能会选择索引 会导致查询速度变慢。因此,您可能会注意到一些查询的运行速度比以前慢。
本页面介绍如何检测查询执行速度的变化;如何检查这些查询的查询执行计划;以及如何在必要时为将来的查询指定不同索引。
检测查询执行速度的变化
进行了以下其中一项更改后,您最有可能会看到查询执行速度变化:
- 对具有二级索引的大量现有数据进行重大更改。
- 添加、更改或删除二级索引。
您可以使用多种不同的工具来确定 Spanner 执行速度比平常慢的特定查询:
- 查询数据分析和查询统计信息。
您通过 Cloud Monitoring 捕获和分析的应用特有指标。例如,您可以监控查询计数指标,以确定某实例在一段时间内的查询数量,并发现用于运行的一条查询的查询优化器版本。
用于衡量应用性能的客户端监控工具。
关于新数据库的说明
在查询包含新插入或导入数据的新创建数据库时,Spanner 可能不会选择最合适的索引,因为查询优化器最多需要 3 天才能自动收集优化器统计信息。如需更早优化新 Spanner 数据库的索引用量,您可以手动构建新的统计信息软件包。
查看架构
找到运行速度变慢的查询后,请查看该查询的 SQL 语句,确定该语句使用的表以及它从这些表中检索的列。
接下来,查找这些表的二级索引。确定是否有任何索引包含您查询的列, 意味着 Spanner 可能会使用其中一个索引来处理查询。
- 如果存在相应索引,下一步是查找 Spanner 用于查询的索引。
如果不存在相应索引,使用
gcloud spanner operations list
命令检查您近期是否删除了某个相应索引:gcloud spanner operations list \ --instance=INSTANCE \ --database=DATABASE \ --filter="@TYPE:UpdateDatabaseDdlMetadata"
如果您删除了某个相应索引,该更改可能已影响查询性能。将二级索引添加回表中。更新后 Spanner 添加索引,再次运行查询并查看其 性能如果性能没有提高,下一步是查找 Spanner 用于查询的索引。
如果您没有删除相应索引,则索引选择不会导致查询性能衰退。查看您的数据或使用模式是否发生了可能影响性能的其他更改。
查找用于查询的索引
如需了解 Spanner 使用哪个索引来处理查询,请在 Google Cloud 控制台中查看查询执行计划:
前往 Google Cloud 控制台中的 Spanner 实例页面。
点击要查询的实例的名称。
在左侧窗格中,点击要查询的数据库,然后点击
Spanner Studio。输入要测试的查询。
在运行查询下拉列表中,选择仅说明。Spanner 会显示查询计划。
在查询计划中查找以下至少一个运算符:
- 表扫描
- 索引扫描
- 交叉应用或分布式交叉应用
以下部分介绍每个运算符的含义。
表扫描运算符
表扫描运算符表示 Spanner 不使用二级索引:
例如,假设 Albums
表没有任何二级索引,您运行以下查询:
SELECT AlbumTitle FROM Albums WHERE STARTS_WITH(AlbumTitle, "Now");
由于没有要使用的索引,因此查询计划包括表扫描运算符。
索引扫描运算符
索引扫描运算符表示 Spanner 在处理查询时使用了二级索引:
例如,假设您向 Albums
表添加索引:
CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle);
然后,运行以下查询:
SELECT AlbumTitle FROM Albums WHERE STARTS_WITH(AlbumTitle, "Now");
AlbumsByAlbumTitle
索引包含 AlbumTitle
,这是查询选择的唯一列。因此,查询计划包括索引扫描运算符。
交叉应用运算符
在某些情况下,Spanner 会使用仅包含一部分 查询选择的列。因此,Spanner 必须将索引与基表联接起来。
发生此类型联接时,查询计划包括具有以下输入内容的交叉应用或分布式交叉应用运算符:
- 表索引的索引扫描运算符
- 拥有索引的表的表扫描运算符
例如,假设您向 Albums
表添加索引:
CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle);
然后,运行以下查询:
SELECT * FROM Albums WHERE STARTS_WITH(AlbumTitle, "Now");
AlbumsByAlbumTitle
索引包含 AlbumTitle
,但查询选择表中的所有列,而不只是 AlbumTitle
。因此,查询计划包括分布式交叉应用运算符,并包含 AlbumsByAlbumTitle
的索引扫描和 Albums
的表扫描作为输入内容。
选择其他索引
找到 Spanner 用于查询的索引后,尝试运行
使用其他索引进行查询,或者扫描基表,而不是
使用索引。如需指定索引,向查询添加 FORCE_INDEX
指令。
如果您发现更快的查询版本,请更新应用以使用该较快的版本。
索引选择准则
请按照以下准则确定要针对查询测试的索引:
如果您的查询满足以下任何条件,请尝试使用基表,而不是二级索引:
- 查询通过基表主键的前缀来检查是否相等(例如,
SELECT * FROM Albums WHERE SingerId = 1
)。 - 有许多行满足查询谓词(例如,
SELECT * FROM Albums WHERE AlbumTitle != "There Is No Album With This Title"
)。 - 查询使用仅包含几百行的基表。
- 查询通过基表主键的前缀来检查是否相等(例如,
如果查询包含选择性非常强的谓词(例如,
REGEXP_CONTAINS
、STARTS_WITH
、<
、<=
、>
、>=
或!=
),请尝试使用所含列与您在谓词中使用的列相同的索引。
测试更新后的查询
使用 Google Cloud 控制台测试更新后的查询,并了解查询需要多长时间 处理查询所需的全部时间
如果您的查询包括查询参数,并且某个查询参数与一些值的绑定比其他值更频繁,则在您的测试中将该查询参数与其中某个值绑定。例如,如果查询包括 WHERE country = @countryId
等谓词,并且您的几乎所有查询都将 @countryId
绑定到值 US
,则在性能测试中将 @countryId
绑定到 US
。此方法可帮助您针对自己最常运行的查询进行优化。
如需在 Google Cloud 控制台中测试更新后的查询,请按以下步骤操作:
前往 Google Cloud 控制台中的 Spanner 实例页面。
点击要查询的实例的名称。
在左侧窗格中,点击要查询的数据库,然后点击
Spanner Studio。输入要测试的查询,包括
FORCE_INDEX
指令,然后点击运行查询。Google Cloud 控制台会打开结果表格标签页,然后显示 查询结果,包括 Spanner 运行所用的时间 服务来处理查询。
该指标不包括其他导致延迟的因素,比如 Google Cloud 控制台解读和显示查询结果所花费的时间。
使用 REST API 以 JSON 格式获取详细的查询性能剖析文件
默认情况下,当您执行查询时,仅返回语句结果。这是由于 QueryMode 设置为 NORMAL
。如需在查询结果中包含详细的执行统计信息,请将 QueryMode 设置为 PROFILE
。
创建会话
更新查询模式之前,请创建一个会话,该会话代表与 Spanner 数据库服务之间的通信通道。
- 点击“
projects.instances.databases.sessions.create
”。 按以下形式提供项目、实例和数据库 ID:
projects/[\PROJECT_ID\]/instances/[\INSTANCE_ID\]/databases/[\DATABASE_ID\]
点击执行。响应会显示您创建的会话,形式如下:
projects/[\PROJECT_ID\]/instances/[\INSTANCE_ID\]/databases/[\DATABASE_ID\]/sessions/[\SESSION\]
您将使用该会话在下一步中执行查询性能剖析。在两次连续使用之间,已创建的会话将最多活跃一个小时,然后将被数据库删除。
对查询进行性能剖析
为查询启用 PROFILE
模式。
- 点击
projects.instances.databases.sessions.executeSql
。 对于 session,输入您在上一步中创建的会话 ID:
projects/[PROJECT_ID]/instances/[INSTANCE_ID]/databases/[DATABASE_ID]/sessions/[SESSION]
对于 Request body,使用以下内容:
{ "sql": "[YOUR_SQL_QUERY]", "queryMode": "PROFILE" }
点击执行。返回的响应将包括查询结果、查询计划和查询的执行统计信息。