Spanner 提供內建資料表,保存了許多使用最多 CPU 的查詢和資料操縱語言 (DML) 陳述式,以及所有查詢的匯總 (包括變更串流查詢)。
可用性
SPANNER_SYS
資料只能透過 SQL 介面取得,例如:
Google Cloud 控制台中資料庫的 Spanner Studio 頁面
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
值的雜湊。對於分區 DML,FPRINT 一律是TEXT
值的雜湊。每個資料列都包含 Spanner 在指定間隔期間擷取特定 SQL 查詢的統計資料,這些資料列包含此特定 SQL 查詢所有執行作業的統計資料。
如果 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 查詢文字,只顯示約 64KB 的內容。
多個查詢的統計資料如果有相同的標記字串,系統會將這些資料分組在單一列中,並以 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 磁碟負載容量,您可以為執行個體新增更多處理單元或節點。詳情請參閱「變更運算容量」。如要改善查詢效能,請考慮將部分資料移至 SSD。 如果工作負載會大量使用磁碟 I/O,建議您將經常存取的資料儲存在 SSD 儲存空間中。從 SSD 存取的資料不會耗用 HDD 磁碟的負載容量。您可以視需要將特定資料表、資料欄或次要索引儲存在 SSD 儲存空間,同時將不常存取的資料儲存在 HDD 儲存空間。詳情請參閱分層儲存空間總覽。 |
失敗查詢的 EXECUTION_COUNT
、AVG_LATENCY_SECONDS
和 LATENCY_DISTRIBUTION
包含因語法不正確或發生暫時性錯誤而失敗的查詢,但重試後成功。這些統計資料不會追蹤失敗和取消的分區 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> |
各項查詢的執行時間直方圖。這些值以秒為單位。
請按照下列方式指定陣列:
如要計算分佈的百分位延遲時間,請使用 詳情請參閱「百分位數和分佈值指標」。 |
資料保留
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_top_minute);
查看查詢的平均延遲時間
下列查詢會傳回特定查詢的平均延遲時間資訊:
SELECT avg_latency_seconds
FROM spanner_sys.query_stats_top_hour
WHERE text LIKE "SELECT x FROM table WHERE x=@foo;";
找出查詢的第 99 個百分位數延遲時間
下列查詢會傳回過去 10 分鐘內執行的查詢,其執行時間的 99 百分位數:
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);
列出特定時間範圍內失敗的查詢
下列查詢會傳回原始資料,包括前一分鐘中,前幾名查詢的執行次數和失敗查詢的平均延遲時間。這些統計資料不會追蹤失敗和已取消的分區 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 點。
收集所選時間範圍內的查詢統計資料
選定要開始調查的時間範圍後,我們會查看 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 或延遲時間之間的關聯。偏差可能表示資料不一致。如果掃描的資料列數量持續偏高,可能表示缺少適當的索引,或是彙整順序不佳。
請執行下列以該查詢的 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 點左右都出現大幅變化。為了瞭解這些數字為何大幅增加,我們將檢查查詢文字,看看結構定義是否有任何變更可能影響查詢。
請使用以下查詢,擷取我們要調查的查詢的查詢文字。
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 最佳做法。