排查性能下降问题

使用 SQL 查询查找数据时,Spanner 会自动使用可能有助于更高效地检索数据的任何二级索引。但在少数情况下,Spanner 可能会选择索引 会导致查询速度变慢。因此,您可能会注意到一些查询的运行速度比以前慢。

本页面介绍如何检测查询执行速度的变化;如何检查这些查询的查询执行计划;以及如何在必要时为将来的查询指定不同索引。

检测查询执行速度的变化

进行了以下其中一项更改后,您最有可能会看到查询执行速度变化:

  • 对具有二级索引的大量现有数据进行重大更改。
  • 添加、更改或删除二级索引。

您可以使用多种不同的工具来确定 Spanner 执行速度比平常慢的特定查询:

关于新数据库的说明

在查询包含新插入或导入数据的新创建数据库时,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 控制台中查看查询执行计划

  1. 前往 Google Cloud 控制台中的 Spanner 实例页面。

    转到“实例”页面

  2. 点击要查询的实例的名称。

  3. 在左侧窗格中,点击要查询的数据库,然后点击 Spanner Studio

  4. 输入要测试的查询。

  5. 运行查询下拉列表中,选择仅说明。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_CONTAINSSTARTS_WITH<<=>>=!=),请尝试使用所含列与您在谓词中使用的列相同的索引。

测试更新后的查询

使用 Google Cloud 控制台测试更新后的查询,并了解查询需要多长时间 处理查询所需的全部时间

如果您的查询包括查询参数,并且某个查询参数与一些值的绑定比其他值更频繁,则在您的测试中将该查询参数与其中某个值绑定。例如,如果查询包括 WHERE country = @countryId 等谓词,并且您的几乎所有查询都将 @countryId 绑定到值 US,则在性能测试中将 @countryId 绑定到 US。此方法可帮助您针对自己最常运行的查询进行优化。

如需在 Google Cloud 控制台中测试更新后的查询,请按以下步骤操作:

  1. 前往 Google Cloud 控制台中的 Spanner 实例页面。

    转到“实例”页面

  2. 点击要查询的实例的名称。

  3. 在左侧窗格中,点击要查询的数据库,然后点击 Spanner Studio

  4. 输入要测试的查询,包括 FORCE_INDEX 指令,然后点击运行查询

    Google Cloud 控制台会打开结果表格标签页,然后显示 查询结果,包括 Spanner 运行所用的时间 服务来处理查询。

    该指标不包括其他导致延迟的因素,比如 Google Cloud 控制台解读和显示查询结果所花费的时间。

使用 REST API 以 JSON 格式获取详细的查询性能剖析文件

默认情况下,当您执行查询时,仅返回语句结果。这是由于 QueryMode 设置为 NORMAL。如需在查询结果中包含详细的执行统计信息,请将 QueryMode 设置为 PROFILE

创建会话

更新查询模式之前,请创建一个会话,该会话代表与 Spanner 数据库服务之间的通信通道。

  1. 点击“projects.instances.databases.sessions.create”。
  2. 按以下形式提供项目实例数据库 ID:

    projects/[\PROJECT_ID\]/instances/[\INSTANCE_ID\]/databases/[\DATABASE_ID\]
    
  3. 点击执行。响应会显示您创建的会话,形式如下:

    projects/[\PROJECT_ID\]/instances/[\INSTANCE_ID\]/databases/[\DATABASE_ID\]/sessions/[\SESSION\]
    

    您将使用该会话在下一步中执行查询性能剖析。在两次连续使用之间,已创建的会话将最多活跃一个小时,然后将被数据库删除。

对查询进行性能剖析

为查询启用 PROFILE 模式。

  1. 点击 projects.instances.databases.sessions.executeSql
  2. 对于 session,输入您在上一步中创建的会话 ID:

    projects/[PROJECT_ID]/instances/[INSTANCE_ID]/databases/[DATABASE_ID]/sessions/[SESSION]
    
  3. 对于 Request body,使用以下内容:

    {
      "sql": "[YOUR_SQL_QUERY]",
      "queryMode": "PROFILE"
    }
    
  4. 点击执行。返回的响应将包括查询结果、查询计划和查询的执行统计信息。