查詢統計資料

Spanner 提供內建資料表,保存了許多使用最多 CPU 的查詢和資料操縱語言 (DML) 陳述式統計資料,以及所有查詢的匯總 (包括變更串流查詢)。

存取查詢統計資料

Spanner 會在 SPANNER_SYS 結構定義中提供查詢統計資料。您可以透過下列方式存取 SPANNER_SYS 資料:

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_COUNTALL_FAILED_AVG_LATENCY_SECONDSCANCELLED_OR_DISCONNECTED_EXECUTION_COUNTTIMED_OUT_EXECUTION_COUNT 統計資料。

  • 先前執行的每個分區 DML 陳述式統計資料,可能會出現在不同間隔。SPANNER_SYS.QUERY_STATS_TOP_10MINUTESPANNER_SYS.QUERY_STATS_TOP_HOUR 分別提供在 10 分鐘和 1 小時內完成的分區 DML 陳述式匯總檢視畫面。如要查看持續時間超過 1 小時的陳述式統計資料,請參閱查詢範例

資料表結構定義

資料欄名稱 類型 說明
INTERVAL_END TIMESTAMP 包含的查詢執行作業在發生時的時間間隔結束時間。
REQUEST_TAG STRING 這項查詢作業的選用要求標記。如要進一步瞭解如何使用標記,請參閱 使用要求標記排解問題
QUERY_TYPE STRING 指出查詢是 PARTITIONED_QUERYQUERYPARTITIONED_QUERY 是指具有從 PartitionQuery API 取得的 partitionToken,或是分區 DML 陳述式。所有其他查詢和 DML 陳述式都會以 QUERY 查詢類型表示。
TEXT STRING SQL 查詢文字,只顯示約 64KB 的內容。

如果多個查詢的標記字串相同,系統會將這些查詢的統計資料分組,並在同一列中顯示,且REQUEST_TAG會比對該標記字串。這個欄位只會顯示其中一個查詢的文字,並截斷至約 64KB。如果是批次 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>

查詢執行時間的直方圖。這些值以秒為單位。

陣列包含單一元素,且具有下列類型:
ARRAY<STRUCT<
  COUNT INT64,
  MEAN FLOAT64,
  SUM_OF_SQUARED_DEVIATION FLOAT64,
  NUM_FINITE_BUCKETS INT64,
  GROWTH_FACTOR FLOAT64,
  SCALE FLOAT64,
  BUCKET_COUNTS ARRAY<INT64>>>

如要進一步瞭解值,請參閱「分布」。

如要從分配情形計算百分位數延遲時間,請使用 SPANNER_SYS.DISTRIBUTION_PERCENTILE(distribution, n FLOAT64) 函式,該函式會傳回估計的第 n 個百分位數。如需相關範例,請參閱「找出查詢的第 99 個百分位數延遲時間」。

詳情請參閱「百分位數和分佈值指標」。

AVG_MEMORY_PEAK_USAGE_BYTES FLOAT64

分散式查詢執行期間的平均尖峰記憶體用量 (以位元組為單位)。

您可以根據這項統計資料,找出可能超出記憶體限制的查詢或資料表資料大小。

AVG_MEMORY_USAGE_PERCENTAGE FLOAT64

在分散式查詢執行期間,所需的平均記憶體用量 (以允許這項查詢的記憶體限制百分比表示)。

這項統計資料只會追蹤查詢執行所需的記憶體。部分運算子會使用額外的緩衝記憶體來提升效能。查詢計畫會顯示使用的額外緩衝記憶體,但不會用於計算 AVG_MEMORY_USAGE_PERCENTAGE,因為緩衝記憶體用於最佳化,並非必要。

使用這項統計資料找出即將達到記憶體用量上限的查詢,如果資料大小增加,這些查詢可能會失敗。如要降低查詢失敗的風險,請參閱 SQL 最佳做法,將這些查詢最佳化,或將查詢分割成多個部分,減少讀取的資料量。

AVG_QUERY_PLAN_CREATION_TIME_SECS FLOAT64

查詢編譯的平均 CPU 作業時間 (以秒為單位),包括查詢執行階段建立作業。

如果這個資料欄的值偏高,請使用參數化查詢

AVG_FILESYSTEM_DELAY_SECS FLOAT64

查詢從檔案系統讀取資料或遭輸入/輸出 (I/O) 封鎖的平均時間。

您可以根據這項統計資料,找出檔案系統 I/O 造成的潛在高延遲。如要減輕影響,請新增索引,或在現有索引中新增 STORING (GoogleSQL) 或 INCLUDE (PostgreSQL) 子句

AVG_REMOTE_SERVER_CALLS FLOAT64

查詢完成的遠端伺服器呼叫 (RPC) 平均次數。

如果掃描相同資料列數的不同查詢,RPC 數量差異極大,請使用這項統計資料找出原因。如果查詢的 RPC 值較高,建議新增索引,或在現有索引中新增 STORING (GoogleSQL) 或 INCLUDE (PostgreSQL) 子句

AVG_ROWS_SPOOLED FLOAT64

查詢陳述式寫入暫存磁碟 (非記憶體) 的平均資料列數。

您可以根據這項統計資料,找出可能導致高延遲的查詢,這類查詢耗用大量記憶體,無法在記憶體中執行。如要減輕影響,請變更 JOIN 順序,或新增提供必要 SORT索引

AVG_DISK_IO_COST FLOAT64

這項查詢的平均費用 (以 Spanner HDD 磁碟負載計算)。

您可以使用這個值,比較在資料庫中執行的讀取作業之間的相對硬碟 I/O 費用。查詢 HDD 儲存空間中的資料時,系統會根據執行個體的 HDD 磁碟負載容量收費。值越高表示您使用的 HDD 磁碟負載越多,查詢速度可能比在 SSD 上執行時慢。此外,如果 HDD 磁碟負載已達上限,查詢效能可能會進一步受到影響。您可以監控執行個體的硬碟磁碟負載總容量,以百分比表示。如要增加 HDD 磁碟的負載容量,可以為執行個體新增更多處理單元或節點。詳情請參閱「變更運算容量」。如要提升查詢效能,也可以考慮將部分資料移至 SSD。

對於會耗用大量磁碟 I/O 的工作負載,建議您將經常存取的資料儲存在 SSD 儲存空間。從 SSD 存取的資料不會耗用 HDD 磁碟負載容量。您可以視需要將特定資料表、資料欄或次要索引儲存在 SSD 儲存空間,同時將不常存取的資料保留在 HDD 儲存空間。詳情請參閱「分層儲存空間總覽」。

EXECUTION_COUNTAVG_LATENCY_SECONDSLATENCY_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>

查詢執行時間的直方圖。 這些值以秒為單位。

請依下列方式指定陣列:
ARRAY<STRUCT<
  COUNT INT64,
  MEAN FLOAT64,
  SUM_OF_SQUARED_DEVIATION FLOAT64,
  NUM_FINITE_BUCKETS INT64,
  GROWTH_FACTOR FLOAT64,
  SCALE FLOAT64,
  BUCKET_COUNTS ARRAY<INT64>>>

如要進一步瞭解值,請參閱「發布」。

如要從分配情形計算百分位數延遲時間,請使用 SPANNER_SYS.DISTRIBUTION_PERCENTILE(distribution, n FLOAT64) 函式,該函式會傳回估計的第 n 個百分位數。如需相關範例,請參閱「找出查詢的第 99 個百分位數延遲時間」。

詳情請參閱「百分位數和分佈值指標」。

資料保留

Spanner 至少會在下列時間範圍保留每個資料表的資料:

  • SPANNER_SYS.QUERY_STATS_TOP_MINUTESPANNER_SYS.QUERY_STATS_TOTAL_MINUTE:涵蓋前 6 個小時的間隔。

  • SPANNER_SYS.QUERY_STATS_TOP_10MINUTESPANNER_SYS.QUERY_STATS_TOTAL_10MINUTE:涵蓋前 4 天的間隔。

  • SPANNER_SYS.QUERY_STATS_TOP_HOURSPANNER_SYS.QUERY_STATS_TOTAL_HOUR:涵蓋前 30 天的間隔。

查詢範例

本節包含多個擷取查詢統計資料的範例 SQL 陳述式。您可以使用用戶端程式庫Google Cloud CLIGoogle 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:00 (世界標準時間) 左右開始發生。

收集所選時間範圍的查詢統計資料

選取開始調查的時間範圍後,我們會查看該時間範圍內 QUERY_STATS_TOTAL_10MINUTE 表格中收集的統計資料。這項查詢的結果可能會指出 CPU 和其他查詢統計資料在該段時間內的變化。

下列查詢會傳回世界標準時間 16:3017: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

在上表,我們可以看到結果表格中的 avg_cpu 欄,顯示在 17:00 結束的醒目顯示間隔中,平均 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 使用率或延遲時間之間的關聯性。偏差可能表示資料不一致。如果掃描的資料列數量持續偏高,可能表示缺少適當的索引,或是彙整排序方式不夠理想。

執行下列陳述式,依據該查詢的 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 最佳做法進行最佳化。

後續步驟