共用方式為


查詢存放區

適用範圍:適用於 PostgreSQL 的 Azure 資料庫 - 彈性伺服器

適用於 PostgreSQL 的 Azure 資料庫彈性伺服器中的 [查詢存放區] 功能會提供方法來追蹤一段時間的查詢效能。 查詢存放區可協助您快速找到執行時間最長又最耗資源的查詢,藉此簡化效能問題疑難排解。 查詢存放區會自動擷取查詢的歷程記錄和執行階段統計資料,並予以保留以供您檢閱。 它會依時間切分資料,以便您查看時態性使用模式。 所有使用者、資料庫和查詢的資料都會儲存在適用於 PostgreSQL 的 Azure 資料庫彈性伺服器執行個體中名為 azure_sys 的資料庫。

啟用查詢存放區

查詢存放區不需額外費用即可供使用。 其為加入功能,因此預設不會在伺服器上予以啟用。 查詢存放區可以針對給定伺服器上的所有資料庫全域予以啟用或停用,但無法根據每個資料庫予以開啟或關閉。

重要事項

請勿在可高載定價層上啟用查詢存放區,因為這會造成效能影響。

在 Azure 入口網站中啟用查詢存放區

  1. 登入 Azure 入口網站,然後選取適用於 PostgreSQL 的 Azure 資料庫彈性伺服器執行個體。
  2. 在功能表的 [設定] 區段中,選取 [伺服器參數]
  3. 搜尋 pg_qs.query_capture_mode 參數。
  4. 根據您想要追蹤最上層查詢還是巢狀查詢 (在函式或程序內執行的查詢),將值設定為 topall,然後選取 [儲存]。 請等候 20 分鐘,以讓第一批資料保存在 azure_sys 資料庫中。

啟用查詢存放區等候取樣

  1. 搜尋 pgms_wait_sampling.query_capture_mode 參數。
  2. 將值設定為 all,然後選取 [儲存]

查詢存放區中的資訊

查詢存放區包含兩個存放區:

  • 執行階段統計資料存放區,用於保存查詢執行統計資料資訊。
  • 等候統計資料存放區,用於保存等候統計資料資訊。

使用查詢存放區的常見案例包括:

  • 判斷查詢在給定時間範圍內的執行次數。
  • 跨時間範圍比較查詢的平均值行時間,查看大幅變化。
  • 識別過去幾小時中執行最久的查詢。
  • 識別前 N 項等候資源的查詢。
  • 了解等候特定查詢的本質。

為了讓空間使用量降到最低,會經過一段固定且可設定的時間範圍,才彙總執行階段統計資料存放區的執行階段執行統計資料。 這些存放區中的資訊可以使用檢視來查詢。

存取查詢存放區資訊

查詢存放區資料會儲存在適用於 PostgreSQL 的 Azure 資料庫彈性伺服器執行個體的 azure_sys 資料庫中。 下列查詢會傳回記錄在查詢存放區中的查詢相關資訊:

SELECT * FROM  query_store.qs_view;

此查詢會傳回等候統計資料的相關資訊:

SELECT * FROM  query_store.pgms_wait_sampling_view;

尋找等候查詢

等候事件類型會依相似性,將不同的等候事件結合成貯體。 查詢存放區提供等候事件類型、特定的等候事件名稱,以及有問題的查詢。 能夠將此等候資訊與查詢執行階段相互關聯,表示您可以更深入了解查詢效能特性從何而來。

以下這些範例說明如何使用查詢存放區中的等候統計資料深入了解您的工作負載:

觀測 動作
高鎖定等候數 查看受影響查詢的查詢文字,並找出目標實體。 在查詢存放區中尋找其他查詢,這些查詢經常執行且/或持續時間很長,並且會修改相同的實體。 找出這些查詢之後,請考慮變更應用程式邏輯,改善並行存取,或使用限制較少的隔離等級。
高緩衝區 IO 等候數 在查詢存放區中尋找實體讀取次數高的查詢。 如果其符合高 IO 等候的查詢,請考慮啟用自動化索引微調功能,以查看其是否可以建議建立一些索引,這可能會減少這些查詢的實體讀取數目。
高記憶體等候數 找出查詢存放區中記憶體耗用量名列前茅的查詢。 這些查詢可能會進一步延遲受影響查詢的進度。

設定選項

啟用查詢存放區時,其會以 pg_qs.interval_length_minutes 伺服器參數所決定的彙總時間範圍長度 (預設為 15 分鐘) 來儲存資料。 針對每個時間範圍,其每個時間範圍最多會儲存 500 個相異查詢。 區分每個查詢唯一性的屬性為 user_id (執行查詢使用者的識別碼)、db_id (查詢執行內容資料庫的識別碼),以及 query_id (可唯一識別所執行查詢的整數值)。 如果在設定的間隔期間,相異查詢的數目達到 500 個,則會解除配置 5% 的所記錄查詢,以騰出更多空間。 首先解除配置的就是執行次數最少的查詢。

下列選項適用於設定查詢存放區參數:

參數 說明 預設值 範圍
pg_qs.interval_length_minutes (*) 查詢存放區的擷取間隔 (以分鐘為單位)。 定義資料持續性的頻率。 15 1 - 30
pg_qs.is_enabled_fs 僅限內部使用:此參數會當作功能覆寫參數使用。 如果顯示為關閉,則會停用查詢存放區,儘管已設定 pg_qs.query_capture_mode 的值。 on onoff
pg_qs.max_plan_size 查詢存放區從查詢計劃文字儲存的最大位元組數目;會截斷較長的計劃。 7500 100 - 10000
pg_qs.max_query_text_length 可儲存的查詢文字長度上限;會截斷過久的查詢。 6000 100 - 10000
pg_qs.parameters_capture_mode 是否及何時擷取查詢位置參數。 capture_parameterless_only capture_parameterless_onlycapture_first_sample
pg_qs.query_capture_mode 要追蹤的陳述式。 none nonetopall
pg_qs.retention_period_in_days 查詢存放區的保留期間範圍 (以天為單位)。 會自動刪除較舊的資料。 7 1 - 30
pg_qs.store_query_plans 查詢計劃是否應儲存在查詢存放區中。 off onoff
pg_qs.track_utility 查詢存放區是否必須追蹤公用程式命令。 on onoff

(*) 靜態伺服器參數,其需要重新啟動伺服器,其值的變更才會生效。

附註

如果您變更 pg_qs.max_query_text_length 參數的值,在進行變更之前擷取的所有查詢文字會繼續使用相同的 query_id 和 sql_query_text。 其可能會造成新值不會生效的印象,但對於之前在查詢存放區中未記錄的查詢,您會看到查詢文字使用新設定的最大長度。 這依設計而定,且會在檢視和函式中說明。 如果您執行 query_store.qs_reset,其會移除查詢存放區目前為止所記錄的所有資訊,包括針對每個查詢識別碼擷取的文字,如果再次執行這些查詢,則新設定的最大長度會套用至所擷取的文字。

下列選項特別適用於等候統計資料:

參數 說明 預設值 範圍
pgms_wait_sampling.history_period 等候事件取樣頻率 (以毫秒為單位)。 100 1 - 600000
pgms_wait_sampling.is_enabled_fs 僅限內部使用:此參數會當作功能覆寫參數使用。 如果顯示為 off,則會停用等候取樣,儘管已設定 pgms_wait_sampling.query_capture_mode 的值也一樣。 on onoff
pgms_wait_sampling.query_capture_mode pgms_wait_sampling 延伸模組必須追蹤的陳述式。 none noneall

附註

pg_qs.query_capture_mode 取代 pgms_wait_sampling.query_capture_mode。 如果 pg_qs.query_capture_modenone,則 pgms_wait_sampling.query_capture_mode 設定無效。

使用 Azure 入口網站為參數取得或設定不同的值。

檢視和函式

您可以查詢查詢存放區所記錄的資訊,或使用 query_store 資料庫的 azure_sys 結構描述中提供的一些檢視和函式加以刪除。 PostgreSQL 公用角色中的任何人都可以使用這些檢視,查看查詢存放區中的資料。 這些檢視僅適用於 azure_sys 資料庫。

查詢的正規化方式是查看其結構,並忽略任何語意不重要的項目,例如常值、常數、別名或大小寫差異。

如果兩個查詢的語意相同,則即使它們針對相同的參考資料行和資料表使用不同的別名,還是會以相同的 query_id 予以識別。 如果兩個查詢只有使用的常值不同,則也會以相同的 query_id 予以識別。 針對以相同的 query_id 識別的查詢,其 sql_query_text 會是下列時間之後第一個所執行查詢的內容:自查詢存放區開始記錄活動之後,或自上次因已執行 query_store.qs_reset 函式而捨棄持續保存的資料之後。

查詢正規化的運作方式

以下是嘗試說明此正規化運作方式的一些範例:

假設您使用下列陳述式來建立資料表:

create table tableOne (columnOne int, columnTwo int);

您會啟用查詢存放區資料收集,而且單一或多個使用者會依此確切順序來執行下列查詢:

select * from tableOne;
select columnOne, columnTwo from tableOne;
select columnOne as c1, columnTwo as c2 from tableOne as t1;
select columnOne as "column one", columnTwo as "column two" from tableOne as "table one";

所有先前的查詢都會共用相同的 query_id。 而且,查詢存放區所保留的文字就是啟用資料收集之後第一個所執行查詢的文字。 因此,其會是 select * from tableOne;

下列一組查詢在正規化之後就會與先前的一組查詢不符,因為 WHERE 子句會使其語意不同:

select columnOne as c1, columnTwo as c2 from tableOne as t1 where columnOne = 1 and columnTwo = 1;
select * from tableOne where columnOne = -3 and columnTwo = -3;
select columnOne, columnTwo from tableOne where columnOne = '5' and columnTwo = '5';
select columnOne as "column one", columnTwo as "column two" from tableOne as "table one" where columnOne = 7 and columnTwo = 7;

不過,這個最後一組中的所有查詢都會共用相同的 query_id,而且用來識別這些查詢的文字全都是批次 select columnOne as c1, columnTwo as c2 from tableOne as t1 where columnOne = 1 and columnTwo = 1; 中第一個查詢的文字。

最後,在下方尋找一些不符合上一個批次中 query_id 查詢的查詢和其不相符的原因:

查詢

select columnTwo as c2, columnOne as c1 from tableOne as t1 where columnOne = 1 and columnTwo = 1;

不相符的原因:資料行清單指的是相同的兩個資料行 (columnOne 和 ColumnTwo),但其參考的順序相反:從上一個批次中的 columnOne, ColumnTwo 到此查詢中的 ColumnTwo, columnOne

查詢

select * from tableOne where columnTwo = 25 and columnOne = 25;

不相符的原因:WHERE 子句中所評估運算式的參照順序會從上一個批次中的 columnOne = ? and ColumnTwo = ? 反轉為此查詢中的 ColumnTwo = ? and columnOne = ?

查詢

select abs(columnOne), columnTwo from tableOne where columnOne = 12 and columnTwo = 21;

不相符的原因:資料行清單中的第一個運算式已不再是 columnOne,而是透過 abs 評估的 columnOne 函式 (abs(columnOne)),這在語意上並不相等。

查詢

select columnOne as "column one", columnTwo as "column two" from tableOne as "table one" where columnOne = ceiling(16) and columnTwo = 16;

不相符的原因:WHERE 子句中的第一個運算式不會再評估 columnOne 與常值相等,而是透過常值評估的 ceiling 函式結果,這在語意上並不相等。

檢視

query_store.qs_view

此檢視會傳回在查詢存放區支援資料表中持續保存的所有資料。 除非時間範圍結束,否則不會顯示目前使用中時間範圍仍要在記憶體內部記錄的資料,而且會收集其記憶體內部動態資料,並將其持續保存至磁碟上所儲存的資料表。 此檢視會針對每個相異資料庫 (db_id)、使用者 (user_id) 和查詢 (query_id) 傳回不同的資料列。

名稱 型別 參考 說明
runtime_stats_entry_id BIGINT 來自 runtime_stats_entries 資料表的識別碼。
user_id oid pg_authid.oid 已執行陳述式的使用者物件識別 (OID)。
db_id oid pg_database.oid 在其中執行陳述式的資料庫物件識別 (OID)。
query_id BIGINT 從陳述式的剖析樹狀結構計算的內部雜湊碼。
query_sql_text varchar(10000) 代表性陳述式的文字。 結構相同的不同查詢會群集在一起;此文字就式叢集中第一個查詢的文字。 查詢文字長度上限的預設值為 6000,而且可以使用查詢存放區參數 pg_qs.max_query_text_length 進行修改。 如果查詢的文字超過這個最大值,則會將其截斷為前 pg_qs.max_query_text_length 個位元組。
plan_id BIGINT 對應至此查詢的計畫識別碼。
start_time 時間戳 會依時間範圍彙總查詢。 伺服器參數 pg_qs.interval_length_minutes 會定義這些視窗的時間範圍 (預設值為 15 分鐘)。 此資料行會對應至記錄此項目的視窗開始時間。
end_time 時間戳 對應至此項目時間範圍的結束時間。
calls BIGINT 此時間範圍中的查詢執行次數。 請注意,針對平行查詢,可驅動查詢執行的後端處理序的每個執行呼叫數目都會對應至 1,再加上每個後端背景工作處理序 (啟動以對可執行執行樹狀結構的平行分支進行共同作業) 的其他許多單位。
total_time 雙精度 查詢總執行時間 (以毫秒為單位)。
min_time 雙精度 查詢最短執行時間 (以毫秒為單位)。
max_time 雙精度 查詢最長執行時間 (以毫秒為單位)。
mean_time 雙精度 查詢平均執行時間 (以毫秒為單位)。
stddev_time 雙精度 查詢執行時間標準差 (以毫秒為單位)。
rows BIGINT 陳述式所擷取或影響的資料列總數。 請注意,針對平行查詢,每個執行的資料列數目都會對應至可驅動查詢執行的後端處理序傳回給用戶端的資料列數目,再加上每個後端背景工作處理序 (啟動以對可執行執行樹狀結構的平行分支進行共同作業) 傳回給驅動執行查詢的後端處理序的所有資料列總和。
shared_blks_hit BIGINT 陳述式的共用區塊快取點擊總數。
shared_blks_read BIGINT 陳述式所讀取的共用區塊總數。
shared_blks_dirtied BIGINT 陳述式所變動的共用區塊總數。
shared_blks_written BIGINT 陳述式所寫入的共用區塊總數。
local_blks_hit BIGINT 陳述式的本機區塊快取點擊總數。
local_blks_read BIGINT 陳述式所讀取的本機區塊總數。
local_blks_dirtied BIGINT 陳述式所變動的本機區塊總數。
local_blks_written BIGINT 陳述式所寫入的本機區塊總數。
temp_blks_read BIGINT 陳述式所讀取的暫存區塊總數。
temp_blks_written BIGINT 陳述式所寫入的暫存區塊總數。
blk_read_time 雙精度 陳述式讀取區塊所花費的總時間 (以毫秒為單位) (如果啟用 track_io_timing,否則為零)。
blk_write_time 雙精度 陳述式寫入區塊所花費的總時間 (以毫秒為單位) (如果啟用 track_io_timing,否則為零)。
is_system_query 布林值 判斷具有user_id = 10 (azuresu) 的角色是否執行查詢。 該使用者具有超級使用者權限,並用來執行控制平面作業。 因為此服務是受控 PaaS 服務,所以只有 Microsoft 是該超級使用者角色的一部分。
query_type 文字 查詢所代表的作業類型。 可能的值為 unknownselectupdateinsertdeletemergeutilitynothingundefined
search_path text 擷取查詢時所設定的 search_path 值。
query_parameters text JSON 物件的文字表示,其值會傳遞至參數化查詢的位置參數。 此資料行只會在兩種情況下填入其值:1) 表示非參數化查詢。 2) 針對參數化查詢,當 pg_qs.parameters_capture_mode 設為 capture_first_sample 時,以及在查詢存放區可以在執行時間擷取查詢參數值的情況下。
parameters_capture_status 文字 查詢所代表的作業類型。 可能的值為 succeeded (查詢未參數化,或是已成功擷取參數化查詢和值)、disabled (查詢已參數化,但未擷取參數,因為 pg_qs.parameters_capture_mode 已設定為 capture_parameterless_only),too_long_to_capture (查詢已參數化,但未擷取參數,因為產生的 JSON 長度會在此檢視的 query_parameters 資料行中浮出水面,因此會視為時間過長而查詢存放區無法保存),too_many_to_capture (查詢已參數化,但未擷取參數,因為參數總數視為過度,而查詢存放區無法保存),serialization_failed (查詢已參數化,但至少其中一個做為參數傳遞的值無法序列化為文字)。

query_store.query_texts_view

此檢視會傳回查詢存放區中的查詢文字資料。 每個相異 query_sql_text 都有一個資料列。

名稱 型別 說明
query_text_id BIGINT query_texts 資料表識別碼
query_sql_text varchar(10000) 代表性陳述式的文字。 結構相同的不同查詢會群集在一起;此文字就式叢集中第一個查詢的文字。
query_type SMALLINT 查詢所代表的作業類型。 在 PostgreSQL <= 14 的版本中,可能的值為 0 (未知)、1 (選取)、2 (更新)、3 (插入)、4 (刪除)、5 (公用程式)、6 (無)。 在 PostgreSQL >= 15 的版本中,可能的值為 0 (未知)、1 (選取)、2 (更新)、3 (插入)、4 (刪除)、5 (合併)、6 (公用程式)、7 (無)。

query_store.pgms_wait_sampling_view

此檢視會傳回查詢存放區中的等候事件資料。 此檢視會針對每個相異資料庫 (db_id)、使用者 (user_id)、查詢 (query_id) 和事件 (event) 傳回不同的資料列。

名稱 型別 參考 說明
start_time 時間戳 會依時間範圍彙總查詢。 伺服器參數 pg_qs.interval_length_minutes 會定義這些視窗的時間範圍 (預設值為 15 分鐘)。 此資料行會對應至記錄此項目的視窗開始時間。
end_time 時間戳 對應至此項目時間範圍的結束時間。
user_id oid pg_authid.oid 執行陳述式使用者的物件識別碼。
db_id oid pg_database.oid 執行陳述式資料庫的物件識別碼。
query_id BIGINT 從陳述式的剖析樹狀結構計算的內部雜湊碼。
event_type 文字 後端正在等候的事件類型。
event 文字 如果後端目前正在等候,則是等候事件名稱。
calls 整數 擷取相同事件的次數。

附註

如需 event_type 檢視的 eventquery_store.pgms_wait_sampling_view 資料行中的可能值清單,請參閱 pg_stat_activity 的官方文件,並尋找參考同名資料行的資訊。

query_store.query_plans_view

此檢視會傳回用來執行查詢的查詢計劃。 每個相異資料庫識別碼和查詢識別碼都會各有一個資料列。 查詢存放區只會記錄非使用量查詢的查詢計劃。

名稱 型別 參考 說明
plan_id BIGINT 來自 EXPLAIN 所產生正規化查詢計畫的雜湊值。 其格式為正規化,因為會排除計畫節點的估計成本,以及緩衝區的使用方式。
db_id oid pg_database.oid 在其中執行陳述式的資料庫物件識別 (OID)。
query_id BIGINT 從陳述式的剖析樹狀結構計算的內部雜湊碼。
plan_text varchar(10000) 陳述式在 costs=false、buffers=false 且 format=text 時的執行計畫。 與 EXPLAIN 所產生的輸出完全相同。

函式

query_store.qs_reset

此函數會捨棄查詢存放區至今收集到的所有統計資料。 其會捨棄已關閉時間範圍的統計資料,這些統計資料已保存至磁碟上的資料表。 其也會捨棄目前時間範圍的統計資料,該時間範圍只存在於記憶體內部。 只有伺服器管理員角色 (azure_pg_admin) 的成員才能執行此函式。

query_store.staging_data_reset

此函式會捨棄查詢存放區收集到記憶體內部的所有統計資料 (即,記憶體中的資料尚未排清至支援查詢存放區持續保存所收集資料的磁碟上資料表)。 只有伺服器管理員角色 (azure_pg_admin) 的成員才能執行此函式。

唯讀模式

當 Azure Database for PostgreSQL 的彈性伺服器處於只讀模式時,例如當 default_transaction_read_only 參數設為 on 時,或因為達到儲存容量而自動啟用只讀模式時,查詢存放區不會記錄任何資料。

在具有讀取複本的伺服器上啟用查詢存放區,並不會自動在任何讀取複本上啟用查詢存放區。 即使您在任何讀取複本加以啟用,查詢存放區也不會記錄在任何讀取複本上執行的查詢,因為其會在只讀模式中運作,直到您將查詢升階為主要複本為止。