Spanner 提供内置表,这些表可以保存 使用最多 CPU 的查询和 DML 语句,以及所有汇总查询 (包括变更数据流查询)。
可用性
SPANNER_SYS
数据只能通过 SQL 接口获得;例如:
数据库的 Spanner Studio 页面 在 Google Cloud 控制台中
gcloud spanner databases execute-sql
命令查询数据分析信息中心
executeQuery
API
不支持 Spanner 提供的其他单次读取方法
SPANNER_SYS
。
按查询分组的 CPU 使用率
下面的表跟踪特定时间段内 CPU 使用率最高的查询:
SPANNER_SYS.QUERY_STATS_TOP_MINUTE
:1 分钟时间段内的查询SPANNER_SYS.QUERY_STATS_TOP_10MINUTE
:10 分钟时间段内的查询SPANNER_SYS.QUERY_STATS_TOP_HOUR
:1 小时时间段内的查询
这些表具有以下属性:
每个表包含表名指定的非重叠时间段长度的数据。
时间段基于时钟时间。1 分钟时间段结束于整点分钟,10 分钟时间段结束于整点 10 分钟(自当前小时数开始),1 小时时间段结束于整点小时数。
例如,在上午 11:59:30,SQL 查询可用的最近时间段为:
- 1 分钟:上午 11:58:00–11:58:59
- 10 分钟:上午 11:40:00–11:49:59
- 1 小时:上午 10:00:00–10:59:59
Spanner 按 SQL 查询的文本对统计信息进行分组。如果查询 使用查询参数, Spanner 会将该查询的所有执行结果组合到一行。如果查询 使用字符串字面量,Spanner 只会在完整 查询文字相同;当任意文字发生变化时,每个查询都会以 单独一行。对于批处理 DML,Spanner 通过在生成指纹之前删除重复的连续相同的语句来规范化批次。
如果存在请求标记,FPRINT 是请求标记的哈希值。否则 它是
TEXT
值的哈希值。每行包含特定 SQL 查询的所有执行的统计信息 指定时间间隔内 Spanner 捕获统计信息的间隔时间。
如果 Spanner 无法存储在该时间段内运行的所有查询, 在指定的时间段内,系统会优先处理 CPU 使用率最高的查询, 。
跟踪的查询包括完成、失败或被用户取消的查询。
统计信息的子集专门指正在运行但未完成的查询:
所有未成功的查询的执行计数和平均延迟时间(以秒为单位)。
超时查询的执行计数。
用户取消或因网络连接问题失败的查询的执行次数。
表中的所有列均可为 null。
表架构
列名 | 类型 | 说明 | |
---|---|---|---|
INTERVAL_END |
TIMESTAMP |
包括的查询执行时所处的时间段的结束时间。 | |
REQUEST_TAG |
STRING |
此查询操作的可选请求标记。如需详细了解如何使用标记,请参阅使用请求标记进行问题排查。 | |
QUERY_TYPE |
STRING |
指示查询是 PARTITIONED_QUERY 还是 QUERY 。PARTITIONED_QUERY
是一个具有从 PartitionQuery API 获取的增加分区令牌的查询。全部
其他查询和 DML 语句由 QUERY 表示
查询类型。
查询统计信息:
分区 DML:
不受支持。
|
|
TEXT |
STRING |
SQL 查询文本,被截断至 64KB 左右。
具有相同标记字符串的多个查询的统计信息归为一行,其中 REQUEST_TAG 与该标记字符串匹配。此字段仅显示其中一个查询的文本,被截断至 64KB 左右。
对于批处理 DML,这组 SQL 语句会展平为一行,并使用英文分号分隔符串联。连续相同的 SQL 文本会在截断之前删除重复。 |
|
TEXT_TRUNCATED |
BOOL |
查询文本是否被截断。 | |
TEXT_FINGERPRINT |
INT64 |
REQUEST_TAG 值的哈希值(如果存在);否则,TEXT 值的哈希值。 |
|
EXECUTION_COUNT |
INT64 |
Spanner 在时间段内查看查询的次数。 | |
AVG_LATENCY_SECONDS |
FLOAT64 |
数据库中每个查询执行的平均时间长度(以秒为单位)。该平均值不包括结果集编码和传输时间以及开销。 | |
AVG_ROWS |
FLOAT64 |
查询返回的平均行数。 | |
AVG_BYTES |
FLOAT64 |
查询返回的数据字节数的平均值,不包括传输编码开销。 | |
AVG_ROWS_SCANNED |
FLOAT64 |
查询扫描的平均行数,不包括已删除的值。 | |
AVG_CPU_SECONDS |
FLOAT64 |
Spanner 在所有实例上花费的平均 CPU 时间(以秒为单位) 执行查询所需的操作。 | |
ALL_FAILED_EXECUTION_COUNT |
INT64 |
查询在间隔期间失败的次数。 | |
ALL_FAILED_AVG_LATENCY_SECONDS |
FLOAT64 |
数据库中每个查询执行失败的平均时间长度(以秒为单位)。该平均值不包括结果集编码和传输时间以及开销。 | |
CANCELLED_OR_DISCONNECTED_EXECUTION_COUNT |
INT64 |
在该时间间隔内,查询被用户取消或由于断开的网络连接而失败的次数。 | |
TIMED_OUT_EXECUTION_COUNT |
INT64 |
查询在时间间隔内超时的次数。 | |
AVG_BYTES_WRITTEN |
FLOAT64 |
语句写入的平均字节数。 | |
AVG_ROWS_WRITTEN |
FLOAT64 |
语句所修改的平均行数。 | |
STATEMENT_COUNT |
INT64 |
汇总到此条目的语句的总和。普通 查询和 DML,则这等于执行次数。对于批处理 DML Spanner 捕获批次中的语句数。 | |
RUN_IN_RW_TRANSACTION_EXECUTION_COUNT |
INT64 |
作为读写事务的一部分运行查询的次数。 此列可帮助您确定是否可以通过将 更改为只读事务。 | |
LATENCY_DISTRIBUTION |
ARRAY<STRUCT> |
查询执行时间的直方图。这些值以秒为单位。
该数组包含一个元素,其类型如下:
如需根据该分布计算百分位延迟时间,
使用 如需了解详情,请参阅百分位和分布值指标。 |
|
AVG_MEMORY_PEAK_USAGE_BYTES |
FLOAT64 |
在分布式查询执行期间,平均峰值内存使用量 (以字节为单位)。 使用此统计信息可确定查询或表数据的大小 可能会遇到内存限制 |
|
AVG_MEMORY_USAGE_PERCENTAGE |
FLOAT64 |
在分布式查询执行期间,所需的平均内存使用量 (以此查询允许的内存限制的百分比)。 此统计信息仅跟踪查询
。有些运算符会使用额外的缓冲内存来提升
性能使用的额外缓冲内存在查询中可见
方案,但不会用于计算 使用此统计信息确定接近内存的查询 且在数据大小增加时可能会失败。接收者 如何降低查询失败的风险 按照 SQL 最佳实践优化这些查询,或者将查询拆分为读取较少数据的部分。 |
|
AVG_QUERY_PLAN_CREATION_TIME_SECS |
FLOAT64 |
查询编译所花费的平均 CPU 时间(以秒为单位),包括 查询运行时创建。 如果此列的值较高,请使用参数化查询。 |
|
AVG_FILESYSTEM_DELAY_SECS |
FLOAT64 |
查询在读取文件系统或 输入/输出 (I/O) 时阻止。 使用此统计信息确定可能由文件导致的高延迟
系统 I/O。如需缓解措施,可添加一个索引
或者添加 |
|
AVG_REMOTE_SERVER_CALLS |
FLOAT64 |
查询已完成的远程服务器调用 (RPC) 的平均数量。 使用此统计信息可确定扫描相同内容的不同查询
行的 RPC 数量截然不同。带有
添加索引可能会提高 RPC 值
或添加一个
|
|
AVG_ROWS_SPOOLED |
FLOAT64 |
查询语句写入临时磁盘(非内存中)的平均行数。 使用此统计信息找出延迟时间可能较长的查询
这类任务占用大量内存,并且无法在内存中执行。为了缓解这种风险
更改 |
EXECUTION_COUNT
、AVG_LATENCY_SECONDS
和 LATENCY_DISTRIBUTION
表示失败
查询包含由于语法不正确或遇到
暂时性错误,但重试成功。
聚合统计信息
还有一些表格可以跟踪 Spanner 在特定时间段内捕获了统计信息:
SPANNER_SYS.QUERY_STATS_TOTAL_MINUTE
:1 分钟时间段内的查询SPANNER_SYS.QUERY_STATS_TOTAL_10MINUTE
:10 分钟时间段内的查询SPANNER_SYS.QUERY_STATS_TOTAL_HOUR
:1 小时时间段内的查询
这些表具有以下属性:
每个表包含表名指定的非重叠时间段长度的数据。
时间段基于时钟时间。1 分钟时间段结束于整点分钟,10 分钟时间段结束于整点 10 分钟(自当前小时数开始),1 小时时间段结束于整点小时数。
例如,在上午 11:59:30,SQL 查询可用的最近时间段为:
- 1 分钟:上午 11:58:00–11:58:59
- 10 分钟:上午 11:40:00–11:49:59
- 1 小时:上午 10:00:00–10:59:59
每行包含在指定时间段内通过数据库执行的所有查询的聚合统计信息。每个时间间隔只能有一行,包括已完成的查询、失败的查询和用户取消的查询。
TOTAL
表中捕获的统计信息可能包含 Spanner 未捕获TOP
表中的数据。这些表中的一些列在 Cloud Monitoring 中显示为指标。 公开的指标包括:
- 查询执行次数
- 查询失败
- 查询延迟时间
- 返回的行数
- 扫描的行数
- 返回的字节数
- 查询 CPU 时间
如需了解详情,请参阅 Spanner 指标。
表架构
列名 | 类型 | 说明 |
---|---|---|
INTERVAL_END |
TIMESTAMP |
包括的查询执行时所处的时间段的结束时间。 |
EXECUTION_COUNT |
INT64 |
Spanner 在相应时间段内查看查询的次数。 |
AVG_LATENCY_SECONDS |
FLOAT64 |
数据库中每个查询执行的平均时间长度(以秒为单位)。该平均值不包括结果集编码和传输时间以及开销。 |
AVG_ROWS |
FLOAT64 |
查询返回的平均行数。 |
AVG_BYTES |
FLOAT64 |
查询返回的数据字节数的平均值,不包括传输编码开销。 |
AVG_ROWS_SCANNED |
FLOAT64 |
查询扫描的平均行数,不包括已删除的值。 |
AVG_CPU_SECONDS |
FLOAT64 |
Spanner 在所有实例上花费的平均 CPU 时间(以秒为单位) 执行查询所需的操作。 |
ALL_FAILED_EXECUTION_COUNT |
INT64 |
查询在间隔期间失败的次数。 |
ALL_FAILED_AVG_LATENCY_SECONDS |
FLOAT64 |
数据库中每个查询执行失败的平均时间长度(以秒为单位)。该平均值不包括结果集编码和传输时间以及开销。 |
CANCELLED_OR_DISCONNECTED_EXECUTION_COUNT |
INT64 |
在该时间间隔内,查询被用户取消或由于断开的网络连接而失败的次数。 |
TIMED_OUT_EXECUTION_COUNT |
INT64 |
查询在时间间隔内超时的次数。 |
AVG_BYTES_WRITTEN |
FLOAT64 |
语句写入的平均字节数。 |
AVG_ROWS_WRITTEN |
FLOAT64 |
语句修改的平均行数。 |
RUN_IN_RW_TRANSACTION_EXECUTION_COUNT |
INT64 |
作为读写事务的一部分运行查询的次数。 此列有助于您确定是否可以通过将某些查询移至只读事务来避免锁争用。 |
LATENCY_DISTRIBUTION |
ARRAY<STRUCT> |
多个查询的执行时间直方图。 这些值以秒为单位。
按如下方式指定数组:
如需根据该分布计算百分位延迟时间,
使用 如需了解详情,请参阅百分位和分布值指标。 |
数据保留
Spanner 至少会为每个表保留以下时间的数据 周期:
SPANNER_SYS.QUERY_STATS_TOP_MINUTE
和SPANNER_SYS.QUERY_STATS_TOTAL_MINUTE
:前 6 个小时中的时间段。SPANNER_SYS.QUERY_STATS_TOP_10MINUTE
和SPANNER_SYS.QUERY_STATS_TOTAL_10MINUTE
:前 4 天中的时间段。SPANNER_SYS.QUERY_STATS_TOP_HOUR
和SPANNER_SYS.QUERY_STATS_TOTAL_HOUR
:前 30 天中的时间段。
示例查询
本部分提供了几个可检索查询统计信息的示例 SQL 语句。您可以使用 客户端库、 Google Cloud CLI 或 Google Cloud 控制台。
列出给定时间段内每个查询的基本统计信息
以下查询可返回前一分钟内顶级查询的原始数据:
SELECT text,
request_tag,
interval_end,
execution_count,
avg_latency_seconds,
avg_rows,
avg_bytes,
avg_rows_scanned,
avg_cpu_seconds
FROM spanner_sys.query_stats_top_minute
ORDER BY interval_end DESC;
列出 CPU 使用率最高的查询
以下查询可返回前一小时 CPU 使用率最高的查询:
SELECT text,
request_tag,
execution_count AS count,
avg_latency_seconds AS latency,
avg_cpu_seconds AS cpu,
execution_count * avg_cpu_seconds AS total_cpu
FROM spanner_sys.query_stats_top_hour
WHERE interval_end =
(SELECT MAX(interval_end)
FROM spanner_sys.query_stats_top_hour)
ORDER BY total_cpu DESC;
查找指定时间段内的总执行次数
以下查询可返回在前一个整 1 分钟时间段内执行的查询总数:
SELECT interval_end,
execution_count
FROM spanner_sys.query_stats_total_minute
WHERE interval_end =
(SELECT MAX(interval_end)
FROM spanner_sys.query_stats_top_minute);
查找查询的平均延迟时间
以下查询可返回特定查询的平均延迟时间信息:
SELECT avg_latency_seconds
FROM spanner_sys.query_stats_top_hour
WHERE text LIKE "SELECT x FROM table WHERE x=@foo;";
查找查询的第 99 百分位延迟时间
以下查询返回各查询执行时间的第 99 个百分位 前 10 分钟内已运行过:
SELECT interval_end, avg_latency_seconds, SPANNER_SYS.DISTRIBUTION_PERCENTILE(latency_distribution[OFFSET(0)], 99.0)
AS percentile_latency
FROM spanner_sys.query_stats_total_10minute
WHERE interval_end =
(SELECT MAX(interval_end)
FROM spanner_sys.query_stats_total_10minute)
ORDER BY interval_end;
将平均延迟时间与第 99 百分位延迟时间进行比较有助于 识别可能执行时间较长的离群查询。
查找扫描最多数据的查询
要衡量某查询扫描的数据量,您可以使用该查询扫描的行数作为统计方式。以下查询可返回前一小时执行的查询所扫描的行数:
SELECT text,
execution_count,
avg_rows_scanned
FROM spanner_sys.query_stats_top_hour
WHERE interval_end =
(SELECT MAX(interval_end)
FROM spanner_sys.query_stats_top_hour)
ORDER BY avg_rows_scanned DESC;
查找写入最多数据的语句
如需衡量查询修改的数据量,您可以使用 DML 写入的行数(或写入的字节数)。以下查询会返回前一小时内由 DML 语句写入的行数:
SELECT text,
execution_count,
avg_rows_written
FROM spanner_sys.query_stats_top_hour
WHERE interval_end =
(SELECT MAX(interval_end)
FROM spanner_sys.query_stats_top_hour)
ORDER BY avg_rows_written DESC;
所有查询的 CPU 总使用率
以下查询可返回前一小时使用的 CPU 小时数:
SELECT (avg_cpu_seconds * execution_count / 60 / 60)
AS total_cpu_hours
FROM spanner_sys.query_stats_total_hour
WHERE interval_end =
(SELECT MAX(interval_end)
FROM spanner_sys.query_stats_total_hour);
列出在指定时间段内失败的查询
以下查询返回原始数据,包括过去一分钟内顶级查询的失败查询次数和平均延迟时间:
SELECT text,
request_tag,
interval_end,
execution_count,
all_failed_execution_count,
all_failed_avg_latency_seconds,
avg_latency_seconds,
avg_rows,
avg_bytes,
avg_rows_scanned,
avg_cpu_seconds
FROM spanner_sys.query_stats_top_minute
WHERE all_failed_execution_count > 0
ORDER BY interval_end;
确定给定时间段内的错误总数
以下查询返回在最近 1 分钟间隔内未能执行的查询总数。
SELECT interval_end,
all_failed_execution_count
FROM spanner_sys.query_stats_total_minute
WHERE interval_end =
(SELECT MAX(interval_end)
FROM spanner_sys.query_stats_top_minute)
ORDER BY interval_end;
列出超时时间最长的查询
以下查询可返回前一小时内超时数量最高的查询。
SELECT text,
execution_count AS count,
timed_out_execution_count AS timeout_count,
avg_latency_seconds AS latency,
avg_cpu_seconds AS cpu,
execution_count * avg_cpu_seconds AS total_cpu
FROM spanner_sys.query_stats_top_hour
WHERE interval_end =
(SELECT MAX(interval_end)
FROM spanner_sys.query_stats_top_hour)
ORDER BY timed_out_execution_count DESC;
查找查询的成功执行和失败执行的平均延迟时间
以下查询返回特定查询的组合平均等待时间,成功执行的平均等待时间和失败执行的平均等待时间。
SELECT avg_latency_seconds AS combined_avg_latency,
all_failed_avg_latency_seconds AS failed_execution_latency,
( avg_latency_seconds * execution_count -
all_failed_avg_latency_seconds * all_failed_execution_count
) / (
execution_count - all_failed_execution_count ) AS success_execution_latency
FROM spanner_sys.query_stats_top_hour
WHERE text LIKE "select x from table where x=@foo;";
使用查询统计信息排查 CPU 使用率过高或查询延迟时间增加的问题
当您需要调查设备上的高 CPU 使用率时,查询统计信息会非常有用 Spanner 数据库,或者单纯想了解 CPU 大量查询形状。检查内容较多的查询 大量数据库资源让 Spanner 用户有机会 降低运营成本,可能改善常规系统延迟。
您可以使用 SQL 代码或查询数据分析 来调查数据库中有问题的查询。以下 介绍了如何使用 SQL 代码调查此类查询。
以下示例重点介绍 CPU 使用情况,但您也可以遵循类似的步骤 排查查询延迟时间增加的问题,并找出 延迟时间只需按延迟时间(而非 CPU 使用率)即可选择时间间隔和查询。
选择要调查的时间段
调查之初是查找您的应用开始出现高 CPU 使用率的时间。例如,如果问题开始出现 大约 2020 年 7 月 24 日下午 5:00(世界协调时间)。
收集所选时间段的查询统计信息
选择开始调查的时间段后,我们将查看在约该时间的 QUERY_STATS_TOTAL_10MINUTE
表中收集的统计信息。此查询的结果可能会显示在该时间段内 CPU 和其他查询统计信息在该时间段内的变化情况
以下查询可返回从 16:30 到 17:30 (世界协调时间)(含)之间的聚合查询统计信息。我们在查询中使用 ROUND
来限制显示小数位数。
SELECT interval_end,
execution_count AS count,
ROUND(avg_latency_seconds,2) AS latency,
ROUND(avg_rows,2) AS rows_returned,
ROUND(avg_bytes,2) AS bytes,
ROUND(avg_rows_scanned,2) AS rows_scanned,
ROUND(avg_cpu_seconds,3) AS avg_cpu
FROM spanner_sys.query_stats_total_10minute
WHERE
interval_end >= "2020-07-24T16:30:00Z"
AND interval_end <= "2020-07-24T17:30:00Z"
ORDER BY interval_end;
运行该查询会产生以下结果。
interval_end | 计数 | 延时 | rows_returned | 字节 | rows_scanned | avg_cpu |
---|---|---|---|---|---|---|
2020-07-24T16:30:00Z | 6 | 0.06 | 5.00 | 536.00 | 16.67 | 0.035 |
2020-07-24T16:40:00Z | 55 | 0.02 | 0.22 | 25.29 | 0.22 | 0.004 |
2020-07-24T16:50:00Z | 102 | 0.02 | 0.30 | 33.35 | 0.30 | 0.004 |
2020-07-24T17:00:00Z |
154 |
1.06 |
4.42 |
486.33 |
7792208.12 |
4.633 |
2020-07-24T17:10:00Z | 94 | 0.02 | 1.68 | 106.84 | 1.68 | 0.006 |
2020-07-24T17:20:00Z | 110 | 0.02 | 0.38 | 34.60 | 0.38 | 0.005 |
2020-07-24T17:30:00Z | 47 | 0.02 | 0.23 | 24.96 | 0.23 | 0.004 |
在上表中,我们看到平均 CPU 时间(结果表中的 avg_cpu 列)在高亮显示的时间间隔(截止17:00)中是最高的。我们还发现平均扫描的行数更高这表示从 16:50 到 17:00 运行的查询价格更高。选择间隔时间 以供在下一步中进一步研究
查找导致高 CPU 使用率的查询
选择要调查的时间间隔后,我们现在查询 QUERY_STATS_TOP_10MINUTE
表。此查询的结果有助于确定哪些查询会导致 CPU 使用率高。
SELECT text_fingerprint AS fingerprint,
execution_count AS count,
ROUND(avg_latency_seconds,2) AS latency,
ROUND(avg_cpu_seconds,3) AS cpu,
ROUND(execution_count * avg_cpu_seconds,3) AS total_cpu
FROM spanner_sys.query_stats_top_10MINUTE
WHERE
interval_end = "2020-07-24T17:00:00Z"
ORDER BY total_cpu DESC;
运行此查询会生成以下结果。
指纹 | 计数 | 延时 | CPU | total_cpu |
---|---|---|---|---|
5505124206529314852 |
30 |
3.88 |
17.635 |
529.039 |
1697951036096498470 |
10 |
4.49 |
18.388 |
183.882 |
2295109096748351518 | 1 | 0.33 | 0.048 | 0.048 |
11618299167612903606 | 1 | 0.25 | 0.021 | 0.021 |
10302798842433860499 | 1 | 0.04 | 0.006 | 0.006 |
123771704548746223 | 1 | 0.04 | 0.006 | 0.006 |
4216063638051261350 | 1 | 0.04 | 0.006 | 0.006 |
3654744714919476398 | 1 | 0.04 | 0.006 | 0.006 |
2999453161628434990 | 1 | 0.04 | 0.006 | 0.006 |
823179738756093706 | 1 | 0.02 | 0.005 | 0.0056 |
结果表格中突出显示的前 2 个查询 平均 CPU 和延迟时间,以及执行次数和 CPU 总数。 请调查这些结果中列出的第一个查询。
比较一段时间内的查询运行情况
通过缩小调查范围,我们可以将注意力集中到 QUERY_STATS_TOP_MINUTE
表。通过比较特定查询随时间的运行情况,我们可以查找返回的行数或字节数,扫描的行数与 CPU 或延迟时间增加之间的相关性。偏差可能表明数据中的非均匀性。持续扫描的大量行可能表明缺乏适当的索引或次优连接顺序。
调查平均 CPU 使用率最高和最高 通过运行以下语句来过滤 text_fingerprint 数据, 。
SELECT interval_end,
ROUND(avg_latency_seconds,2) AS latency,
avg_rows AS rows_returned,
avg_bytes AS bytes_returned,
avg_rows_scanned AS rows_scanned,
ROUND(avg_cpu_seconds,3) AS cpu,
FROM spanner_sys.query_stats_top_minute
WHERE text_fingerprint = 5505124206529314852
ORDER BY interval_end DESC;
运行此查询会返回以下结果。
interval_end | 延时 | rows_returned | bytes_returned | rows_scanned | CPU |
---|---|---|---|---|---|
2020-07-24T17:00:00Z | 4.55 | 21 | 2365 | 30000000 | 19.255 |
2020-07-24T16:00:00Z | 3.62 | 21 | 2365 | 30000000 | 17.255 |
2020-07-24T15:00:00Z | 4.37 | 21 | 2365 | 30000000 | 18.350 |
2020-07-24T14:00:00Z | 4.02 | 21 | 2365 | 30000000 | 17.748 |
2020-07-24T13:00:00Z | 3.12 | 21 | 2365 | 30000000 | 16.380 |
2020-07-24T12:00:00Z | 3.45 | 21 | 2365 | 30000000 | 15.476 |
2020-07-24T11:00:00Z | 4.94 | 21 | 2365 | 30000000 | 22.611 |
2020-07-24T10:00:00Z | 6.48 | 21 | 2365 | 30000000 | 21.265 |
2020-07-24T09:00:00Z | 0.23 | 21 | 2365 | 5 | 0.040 |
2020-07-24T08:00:00Z | 0.04 | 21 | 2365 | 5 | 0.021 |
2020-07-24T07:00:00Z | 0.09 | 21 | 2365 | 5 | 0.030 |
检查上述结果,我们发现扫描的行数,使用的 CPU 和延迟时间都在上午 9:00 左右发生了显着变化。为了了解这些数字急剧增加的原因,我们将检查查询文本,并查看架构中的任何更改是否可能影响查询。
使用以下查询来检索要调查的查询的查询文本。
SELECT text,
text_truncated
FROM spanner_sys.query_stats_top_hour
WHERE text_fingerprint = 5505124206529314852
LIMIT 1;
这会返回以下结果。
text | text_truncated |
---|---|
从 o_custkey = 36901 的订单中选择 *; | 否 |
通过检查返回的查询文本,我们意识到该查询会在名为 o_custkey
的字段中进行过滤。这是 orders
表上的非键列。发生这种情况时,该列中的索引将在上午 9 点左右删除。这解释了此查询的费用变化。我们可以重新添加该索引,如果该查询很少运行,请确定没有索引,并接受更高的读取费用。
到目前为止,我们的调查工作重点放在了成功完成的查询中,并发现了数据库性能下降的一些原因。下一步,我们将着重介绍失败的或已取消的查询,并介绍如何检查数据以获取更多洞见。
调查失败的查询
未完成的查询仍会在超时前、被取消前或失败之前消耗资源。Spanner 会跟踪 失败的查询以及成功的查询所消耗的执行数和资源 。
如需检查失败的查询是否会影响系统利用率,我们首先可以检查相关时间间隔中有多少查询失败。
SELECT interval_end,
all_failed_execution_count AS failed_count,
all_failed_avg_latency_seconds AS latency
FROM spanner_sys.query_stats_total_minute
WHERE
interval_end >= "2020-07-24T16:50:00Z"
AND interval_end <= "2020-07-24T17:00:00Z"
ORDER BY interval_end;
interval_end | failed_count | 延时 |
---|---|---|
2020-07-24T16:52:00Z | 1 | 15.211391 |
2020-07-24T16:53:00Z | 3 | 58.312232 |
在进一步调查时,我们可以利用以下查询找出最有可能失败的查询。
SELECT interval_end,
text_fingerprint,
execution_count,
avg_latency_seconds AS avg_latency,
all_failed_execution_count AS failed_count,
all_failed_avg_latency_seconds AS failed_latency,
cancelled_or_disconnected_execution_count AS cancel_count,
timed_out_execution_count AS to_count
FROM spanner_sys.query_stats_top_minute
WHERE all_failed_execution_count > 0
ORDER BY interval_end;
interval_end | text_fingerprint | execution_count | failed_count | cancel_count | to_count |
---|---|---|---|---|---|
2020-07-24T16:52:00Z | 5505124206529314852 | 3 | 1 | 1 | 0 |
2020-07-24T16:53:00Z | 1697951036096498470 | 2 | 1 | 1 | 0 |
2020-07-24T16:53:00Z | 5505124206529314852 | 5 | 2 | 1 | 1 |
如上表所示,使用指纹 5505124206529314852
的查询在不同时间间隔内多次失败。如果遇到此类故障,那么比较成功和失败的运行延迟时间会比较有趣。
SELECT interval_end,
avg_latency_seconds AS combined_avg_latency,
all_failed_avg_latency_seconds AS failed_execution_latency,
( avg_latency_seconds * execution_count -
all_failed_avg_latency_seconds * all_failed_execution_count
) / (
execution_count - all_failed_execution_count ) AS success_execution_latency
FROM spanner_sys.query_stats_top_hour
WHERE text_fingerprint = 5505124206529314852;
interval_end | combined_avg_latency | failed_execution_latency | success_execution_latency |
---|---|---|---|
2020-07-24T17:00:00Z | 3.880420 | 13.830709 | 2.774832 |
运用最佳实践
确定了要优化的候选查询后,我们接下来可以查看查询配置文件,并尝试使用 SQL 最佳做法进行优化。
后续步骤
使用最早的活跃查询来确定运行时间最长的活跃查询。
详细了解调查高 CPU 利用率。
了解其他内省工具。
有关 Spanner 为每个数据库存储的其他信息,请参阅 数据库的信息架构表。
详细了解 SQL 最佳实践 Spanner。