本文說明 Spanner 以內建資料表形式提供的查詢統計資料。您可以使用 SQL 陳述式,從 SPANNER_SYS.QUERY_STATS* 資料表擷取統計資料。
查詢統計資料的使用時機
如需調查效能問題或最佳化 Spanner 資料庫的查詢,查詢統計資料就非常實用。您可以使用查詢統計資料,調查 CPU 用量偏高的問題、排解查詢延遲時間過長的問題,或減少記憶體用量。
如何存取查詢統計資料
。Spanner 會在 SPANNER_SYS 結構定義中提供查詢統計資料。您可以透過下列方式存取 SPANNER_SYS 資料:
Google Cloud 控制台中的資料庫 Spanner Studio 頁面。
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 會將該查詢的所有執行作業分組到同一列。如果查詢使用的字串常值無法自動轉換為參數,則只有在完整查詢文字完全相同時,Spanner 才會將統計資料分組;如果任何文字不同,每項查詢都會顯示為獨立資料列。如果是批次 DML,Spanner 會先簡化連續的相同陳述式,將批次正規化,然後才產生指紋。
如果要求標記存在,TEXT_FINGERPRINT 是要求標記的雜湊。如果沒有,則為
TEXT值的雜湊。如果是分區 DML,TEXT_FINGERPRINT 一律是TEXT值的雜湊。每個資料列都包含特定 SQL 查詢的所有執行作業統計資料,Spanner 會在指定時間間隔內擷取這些統計資料。
如果 Spanner 無法儲存指定時間範圍內執行的所有查詢,系統會優先處理 CPU 用量最高的查詢。
追蹤的查詢包括已完成、失敗或由使用者取消的查詢。
部分統計資料僅適用於已執行但未完成的查詢:
所有失敗查詢的執行次數和平均延遲時間 (以秒為單位)。
逾時查詢的執行次數。
使用者取消或因網路連線問題而失敗的查詢執行次數。
資料表中的所有資料欄都可為空值。
先前執行的分區 DML 陳述式查詢統計資料具有下列屬性:
每個成功的分區 DML 陳述式都嚴格計為一次執行。失敗、取消或執行中的分區 DML 陳述式,執行次數為零。
系統不會追蹤分區 DML 的
ALL_FAILED_EXECUTION_COUNT、ALL_FAILED_AVG_LATENCY_SECONDS、CANCELLED_OR_DISCONNECTED_EXECUTION_COUNT和TIMED_OUT_EXECUTION_COUNT統計資料。先前執行的每個分區 DML 陳述式,其統計資料可能會顯示在不同間隔中。
SPANNER_SYS.QUERY_STATS_TOP_10MINUTE和SPANNER_SYS.QUERY_STATS_TOP_HOUR分別提供在 10 分鐘和 1 小時內完成的分區 DML 陳述式匯總檢視畫面。如要查看執行時間超過 1 小時的陳述式統計資料,請參閱查詢範例。
資料表結構定義
| 資料欄名稱 | 類型 | 說明 | |
|---|---|---|---|
INTERVAL_END |
TIMESTAMP |
所含查詢執行作業的時間間隔結束時間。 | |
REQUEST_TAG |
STRING |
這項查詢作業的選用要求標記。如要進一步瞭解如何使用標記,請參閱「 使用要求標記排解問題」。 | |
QUERY_TYPE |
STRING |
指出查詢是 PARTITIONED_QUERY 還是 QUERY。PARTITIONED_QUERY 是指含有從 PartitionQuery API 取得的 partitionToken 查詢,或分區 DML 陳述式。所有其他查詢和 DML 陳述式都會以 QUERY 查詢類型表示。 |
|
TEXT |
STRING |
SQL 查詢文字,截斷至約 64 KB。 如果多個查詢具有相同的標記字串,系統會將這些查詢的統計資料分組到單一資料列,並以 REQUEST_TAG 比對該標記字串。這個欄位只會顯示其中一項查詢的文字,並截斷至約 64 KB。如果是批次 DML,SQL 陳述式組合會簡化為單一資料列,並以分號分隔符號串連。連續相同的 SQL 文字會在截斷前簡化。 |
|
TEXT_TRUNCATED |
BOOL |
查詢文字是否只顯示部分內容。 | |
TEXT_FINGERPRINT |
INT64 |
如有 REQUEST_TAG 值,指紋為其雜湊;如果沒有,則為 TEXT 值的雜湊。對應至稽核記錄中的 query_fingerprint 欄位 |
|
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 |
查詢陳述式寫入暫存磁碟 (非記憶體內) 的平均資料列數。 這項統計資料可用來找出可能導致高延遲的查詢,這類查詢會耗用大量記憶體,且無法在記憶體中執行。如要緩解這個問題,請變更 |
|
AVG_DISK_IO_COST |
FLOAT64 |
這項查詢在 Spanner HDD 磁碟負載方面的平均費用。 您可以使用這個值,比較資料庫中執行的讀取作業之間的相對 HDD I/O 費用。查詢 HDD 儲存空間中的資料時,系統會根據執行個體的 HDD 磁碟負載容量收取費用。值越高,代表您使用的 HDD 磁碟負載越多,查詢速度可能比在 SSD 上執行時慢。此外,如果 HDD 磁碟負載已滿,查詢效能可能會進一步受到影響。您可以監控執行個體的 HDD 磁碟負載總容量百分比。如要增加 HDD 磁碟負載容量,可以為執行個體新增更多處理單元或節點。詳情請參閱「變更運算能力」。如要提升查詢效能,也可以考慮將部分資料移至固態硬碟。 如果工作負載會耗用大量磁碟 I/O,建議您將經常存取的資料儲存在 SSD 儲存空間。從 SSD 存取資料不會耗用 HDD 磁碟負載容量。您可以視需要將特定資料表、資料欄或次要索引儲存在 SSD 儲存空間,並將不常存取的資料保留在 HDD 儲存空間。詳情請參閱「分級儲存空間總覽」。 |
|
LATENCY_DISTRIBUTION_JSON_STRING |
STRING |
查詢執行時間的直方圖。值以秒為單位。
GoogleSQL 和 PostgreSQL 方言資料庫支援這個資料欄。這個資料欄包含發布版本。 如要從分布情形計算百分位數延遲時間,請使用 詳情請參閱「百分位數和分布值指標」。 |
|
AVG_COLUMNAR_READ_SHARE |
FLOAT64 |
從資料欄儲存空間讀取的位元組平均百分比,除以從資料列和資料欄儲存空間讀取的位元組總數,以 0 到 1 之間的分數表示。 這項統計資料可用於監控查詢中的資料欄引擎用量。詳情請參閱「監控資料欄引擎效能」。 |
|
QUERY_OPTIMIZER_VERSIONS |
ARRAY<INT64> |
在這個時間範圍內,用於查詢的查詢最佳化工具版本。 |
|
STATISTICS_PACKAGE_NAMES |
ARRAY<STRING> |
在這個時間範圍內,用於查詢的統計資料套件名稱。 |
|
CPU_SECONDS_DISTRIBUTION |
ARRAY<STRUCT> |
Spanner 在所有作業中執行查詢所花費的 CPU 作業時間直方圖。值以秒為單位。
陣列結構如下:
如要從分布中計算 CPU 秒數百分位數,請使用 |
|
CPU_SECONDS_DISTRIBUTION_JSON_STRING |
STRING |
GoogleSQL 方言和 PostgreSQL 方言資料庫支援這個資料欄。 如要從分布中計算 CPU 秒數百分位數,請使用 |
|
ROW_SCANNED_DISTRIBUTION |
ARRAY<STRUCT> |
查詢掃描的資料列數直方圖,不含已刪除的值。
陣列結構如下:
如要計算從分布掃描的資料列百分位數,請使用 |
|
ROW_SCANNED_DISTRIBUTION_JSON_STRING |
STRING |
GoogleSQL 方言和 PostgreSQL 方言資料庫支援這個資料欄。 如要計算從分布掃描的資料列百分位數,請使用 |
EXECUTION_COUNT、AVG_LATENCY_SECONDS、LATENCY_DISTRIBUTION 和 LATENCY_DISTRIBUTION_JSON_STRING 失敗查詢包括因語法不正確而失敗的查詢,或遇到暫時性錯誤但在重試時成功的查詢。這些統計資料不會追蹤失敗和取消的分區 DML 陳述式。
匯總統計資料
此外,還有一些資料表會追蹤 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> |
查詢執行時間的直方圖。值以秒為單位。
請按照下列方式指定陣列:
如要從分布情形計算百分位數延遲時間,請使用 詳情請參閱「百分位數和分布值指標」。 |
LATENCY_DISTRIBUTION_JSON_STRING |
STRING |
查詢執行時間的直方圖。值以秒為單位。
GoogleSQL 方言和 PostgreSQL 方言資料庫支援這個資料欄。這個資料欄包含發布版本。 如要從分布情形計算百分位數延遲時間,請使用 詳情請參閱「百分位數和分布值指標」。 |
AVG_COLUMNAR_READ_SHARE |
FLOAT64 |
從資料欄儲存空間讀取的位元組平均百分比,除以從資料列和資料欄儲存空間讀取的位元組總數,以 0 到 1 之間的分數表示。 這項統計資料可用於監控查詢中的資料欄引擎用量。詳情請參閱「監控資料欄引擎效能」。 |
CPU_SECONDS_DISTRIBUTION |
ARRAY<STRUCT> |
Spanner 在所有作業中執行查詢所花費的 CPU 作業時間直方圖。值以秒為單位。
陣列結構如下:
如要從分布中計算 CPU 秒數百分位數,請使用 |
CPU_SECONDS_DISTRIBUTION_JSON_STRING |
STRING |
GoogleSQL 方言和 PostgreSQL 方言資料庫支援這個資料欄。 如要從分布中計算 CPU 秒數百分位數,請使用 |
ROW_SCANNED_DISTRIBUTION |
ARRAY<STRUCT> |
查詢掃描的資料列數直方圖,不含已刪除的值。
陣列結構如下:
如要計算從分布掃描的資料列百分位數,請使用 |
ROW_SCANNED_DISTRIBUTION_JSON_STRING |
STRING |
GoogleSQL 方言和 PostgreSQL 方言資料庫支援這個資料欄。 如要計算從分布掃描的資料列百分位數,請使用 |
資料保留
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 控制台執行這些 SQL 陳述式。
列出指定時間範圍內每項查詢的基本統計資料
下列查詢會傳回前一分鐘中,前幾名查詢的原始資料:
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;
列出執行時間超過一小時的分區 DML 陳述式統計資料
下列查詢會傳回過去幾小時內,熱門分區 DML 查詢的執行次數和平均寫入資料列數:
SELECT text,
request_tag,
interval_end,
sum(execution_count) as execution_count,
sum(avg_rows_written*execution_count)/sum(execution_count) as avg_rows_written
FROM spanner_sys.query_stats_top_hour
WHERE starts_with(text, "UPDATE") AND query_type = "PARTITIONED_QUERY"
group by text, request_tag, interval_end
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_total_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 分鐘內執行的查詢中,執行時間的第 99 個百分位數。
如果是 GoogleSQL 方言資料庫,可以使用 LATENCY_DISTRIBUTION 資料欄:
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;
如果是 PostgreSQL 方言資料庫,請改用 LATENCY_DISTRIBUTION_JSON_STRING 資料欄:
SELECT interval_end, avg_latency_seconds, SPANNER_SYS.DISTRIBUTION_PERCENTILE(latency_distribution_json_string, 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;
找出掃描最多資料的查詢
您可以使用查詢掃描的資料列數,來測量查詢所掃描的資料量。下列查詢會傳回前一小時查詢所掃描的資料列數。
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);
列出指定時間範圍內失敗的查詢
下列查詢會傳回原始資料,包括前一分鐘內熱門查詢的執行次數和失敗查詢的平均延遲時間。這些統計資料不會追蹤失敗和取消的分區 DML 陳述式。
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 分鐘內執行失敗的查詢總數。這些統計資料不會追蹤失敗和取消的分區 DML 陳述式。
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;
找出查詢執行成功和失敗的平均延遲時間
下列查詢會傳回特定查詢的合併平均延遲時間、成功執行的平均延遲時間,以及失敗執行的平均延遲時間。這些統計資料不會追蹤失敗和取消的分區 DML 陳述式。
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 使用率偏高或查詢延遲時間增加的問題
如要調查 Spanner 資料庫 CPU 使用率過高的問題,或想瞭解資料庫中 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 |
在上表中,請注意,在 17:00 結束的醒目顯示時間間隔中,平均 CPU 作業時間 (結果資料表中的「avg_cpu」avg_cpu欄) 最高。此外,平均掃描的資料列數也大幅增加。這表示 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 或延遲時間升高之間的關聯。如果出現偏差,可能表示資料不一致。如果掃描的資料列數量持續偏高,可能代表缺少適當的索引,或 join 順序不佳。
執行下列陳述式,依據該查詢的 text_fingerprint 進行篩選,調查平均 CPU 使用率和延遲時間最高的查詢。
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_truncated |
|---|---|
| select * from orders where o_custkey = 36901; | false |
查看傳回的查詢文字,您會發現查詢會篩選名為 o_custkey 的欄位。這是 orders 資料表中的非鍵資料欄。原來,該資料欄原本有索引,但在上午 9 點左右遭到捨棄。這就是這項查詢費用變動的原因。您可以重新加入索引,或者如果查詢不常執行,也可以決定不使用索引,並接受較高的讀取成本。
到目前為止,調查重點在於成功完成的查詢,並找出資料庫效能降低的原因。在下一個步驟中,請著重於失敗或取消的查詢,並檢查相關資料,取得更多深入分析。
調查失敗的查詢
未成功完成的查詢在逾時、取消或失敗前,仍會耗用資源。Spanner 會追蹤失敗和成功查詢的執行次數和消耗的資源。這些統計資料不會追蹤失敗和取消的分區 DML 陳述式。
如要確認失敗的查詢是否為系統使用率的主要原因,請先確認在感興趣的時間間隔內有多少查詢失敗。
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 為每個資料庫儲存的其他資訊,請參閱資料庫的資訊結構定義資料表。
進一步瞭解 Spanner 的 SQL 最佳做法。