| PostgreSQL 7.4 文檔 | ||||
|---|---|---|---|---|
| Prev | Fast Backward | Chapter 23. 監控數據庫的活動 | Fast Forward | Next |
PostgreSQL 的 統計收集器是一個支持收集和匯報服務器活躍性信息的子系統。 目前,這個收集器可以給對表和索引的訪問計數,包括磁盤塊的數量和獨立行的項。 它還可以判斷當前其它服務器進程在執行的命令是什麼。
因為統計收集給查詢處理增加了一些過熱,所以你可以把系統配置為收集信息,也可以配置為不收集信息。 這個是由配置參數控制的,這些配置參數通常在 postgresql.conf 裡設置(參閱 Section 16.4 獲取有關設置配置參數的細節)。
要想讓統計收集器運行起來, 參數 stats_start_collector 必須設置為真。 這個設置是缺省設置,也是建議設置,但是如果你對統計不感興趣並且想把所有過荷都擠出去, 那麼可以把它設置為假。(不過,省下來的東西並不多。) 請注意這個選項在服務器運行的時候並不能改變。
參數 stats_command_string, stats_block_level,和 stats_row_level 控制實際發送給收集器的數量, 因此也決定了會產生多少運行時過熱。這些選項分別決定一個服務器進程是否發送它的當前命令字串, 磁盤塊層次的訪問統計,以及行層次的訪問統計給收集器。 通常這些參數在 postgresql.conf 中設置, 因此它們適用于所有服務器進程,但是我們也可以在獨立的會話裡用 SET 命令把它們打開或者關閉。 (為避免普通用戶把它們的活躍性隱藏不給管理員看,只有超級用戶允許用 SET 命令修改這些參數。)
注意: 因為參數 stats_command_string, stats_block_level,和 stats_row_level 缺省時false, 索引實際上缺省配置中不收集任何統計信息。 打開這些配置變量中的一個或多個可以顯著增加統計收機器生成的有用信息的數量,代價是增加了一點運行時開銷。
有一些預定義的視圖可以用于顯示統計收集的結果,在 Table 23-1 裡列出。另外, 我們可以使用下層的統計函數制作自己的客戶化視圖。
在使用統計觀察當前活躍性的時候,你必須意識到這些信息並不是實時更新的。 每個獨立的服務器進程只是在等待另外一條客戶端命令的時候才向收集器傳送新的訪問計數; 因此正在處理的查詢並不影響顯示出來的總數。 同樣,收集器本身也時最多每 pgstat_stat_interval毫秒 (缺省是 500)發送一次新的總數。因此顯示的總數總是落後于實際活動。
另外一個需要著重指出的問題是,在請求服務器進程顯示任何這些統計信息的時候, 它首先抓取收集器進程發出的最新的總計。然後它就接著拿這些數據作為所有統計視圖和函數的快照, 直到它當前的事務的結束。 因此統計在你當前事務的持續期間內時不會改變的。這是一個特性, 而不是一個毛病,因為這樣就允許你在統計上執行幾個查詢並且對結果進行相關性的檢查而又不用擔心這些數字會背著你變化。 但是如果你想看每個查詢的新的結果,那麼就要記住在任何事務塊外面處理這些查詢。
Table 23-1. 標準統計視圖
| 視圖名字 | 描述 |
|---|---|
| pg_stat_activity | 每個服務器進程一行,顯示進程ID,數據庫,用戶,當前查詢和當前查詢開始執行的時間。 只有在打開 stats_command_string 參數的時候, 才能得到報告當前查詢的相關信息的各個字段。 另外,除非檢查這些字段的用戶是超級用戶或者是擁有正在匯報的進程的同一個用戶,否則它們顯示為空。 (請注意因為收集器的報告延遲,當前查詢只是對長時間運行的查詢及時更新。) |
| pg_stat_database | 每個數據庫一行,顯示激活的後端的數量,提交的事務總數以及在該數據庫中回卷數目的總數, 讀取的磁盤塊的總數,以及緩衝區命中的總數(也就是中所需要的塊已經在緩衝區中找到,從而避免了讀取塊的動作)。 |
| pg_stat_all_tables | 當前數據庫中每個表一行,裡面有順序掃描和索引掃描的總數, 每種類型的掃描返回的元組的總數以及元組插入,更新,和刪除的總數。 |
| pg_stat_sys_tables | 和pg_stat_all_tables一樣,只不過只顯示系統表。 |
| pg_stat_user_tables | 和pg_stat_all_tables一樣,只不過只顯示用戶表。 |
| pg_stat_all_indexes | 當前數據庫的每個索引一行,包括使用了該索引的索引掃描總數, 索引元組讀取的總數以及成功抓取的堆元組的數目(如果有些索引記錄指向過期的堆元組,那麼這個數目可能少一些。) |
| pg_stat_sys_indexes | 和pg_stat_all_indexes一樣,只不過只包含那些顯示為系統表上的索引。 |
| pg_stat_user_indexes | 和pg_stat_all_indexes一樣,只不過只包含那些顯示為用戶表上的索引。 |
| pg_statio_all_tables | 當前數據庫中每個表一行,包含從該表中讀取的磁盤塊總數, 緩衝區命中的總數,在該表上所有索引的磁盤塊讀取和緩衝區命中總數, 在該表的輔助 TOAST 表(如果存在)上的磁盤塊讀取和緩衝區命中總數, 以及 TOAST 表的索引的磁盤塊讀取和緩衝區命中總數. |
| pg_statio_sys_tables | 和pg_statio_all_tables一樣,只不過只顯示系統表. |
| pg_statio_user_tables | 和pg_statio_all_tables一樣,只不過只顯示用戶表. |
| pg_statio_all_indexes | 當前數據庫中每個索引一行,包含該索引的磁盤塊讀取和緩衝區命中的數目。 |
| pg_statio_sys_indexes | 和pg_statio_all_indexes一樣,只不過只顯示系統表。 |
| pg_statio_user_indexes | 和pg_statio_all_indexes一樣,只不過只顯示用戶表。 |
| pg_statio_all_sequences | 當前數據庫中每個序列對象一個,包含該序列磁盤讀取和緩衝區命中的數目。 |
| pg_statio_sys_sequences | 和pg_statio_all_sequences一樣,只不過只顯示系統序列。 (準確地說,我們沒有定義系統序列,所以這個視圖總是空的。) |
| pg_statio_user_sequences | 和pg_statio_all_sequences一樣,只不過只顯示用戶序列。 |
每索引的統計對于判斷哪個索引得到使用以及它們的效果非常有用。
pg_statio_ 系列視圖在判斷緩衝的效果的時候特別有用。 在實際磁盤讀取遠表緩衝命中小的時候,我們就知道這個緩衝基本滿足所有讀要求,因此不需要進行內核調用。 但是,這些統計並未給出所有信息:由于 PostgreSQL 處理磁盤的方式,不在 PostgreSQL 緩衝區緩存的數據可能仍然駐留在內核的 I/O 緩存中, 因此仍然可能不經過物理讀取而抓取。 對獲取 PostgreSQL 的 I/O 行為的更多細節感興趣的用戶可以結合使用 PostgreSQL 的統計收集器和可以分析內核 I/O 處理的操作系統工具來獲取更多細節。
其它查看統計的方法可以通過書寫使用下層統計訪問函數的查詢來設置,這些下層統計訪問函數和標準視圖裡使用的是一樣的。 這些函數在Table 23-2 中列出。 就某數據庫進行訪問的函數接受一個數據庫 OID 為參數來標識需要報告哪個數據庫。 就某表或者某索引進行訪問的函數接受一個表或者索引的 OID。 (請注意這些函數只能看到在當前數據庫裡的表和索引)。 就某後端進行訪問的函數接受一個後端 ID 號,其範圍從一到當前活躍後端的數目。
Table 23-2. 統計訪問函數
| 函數 | 返回類型 | 描述 |
|---|---|---|
| pg_stat_get_db_numbackends(oid) | integer | 處理數據庫的活躍的後端進程數目。 |
| pg_stat_get_db_xact_commit(oid) | bigint | 數據庫中已提交事務數量。 |
| pg_stat_get_db_xact_rollback(oid) | bigint | 數據庫中回卷的事務數量 |
| pg_stat_get_db_blocks_fetched(oid) | bigint | 數據庫中磁盤塊抓取請求總數 |
| pg_stat_get_db_blocks_hit(oid) | bigint | 為數據庫在緩衝區中找到的磁盤塊抓取請求總數 |
| pg_stat_get_numscans(oid) | bigint | 如果參數是一個表,那麼就是進行的順序掃描的數目, 如果是一個索引,那麼就是索引掃描的數目。 |
| pg_stat_get_tuples_returned(oid) | bigint | 如果參數是一個表,那麼就是順序掃描讀取的元組數目, 如果是一個索引,那麼就是索引元組的數目 |
| pg_stat_get_tuples_fetched(oid) | bigint | 如果參數是一個表,那麼就是順序掃描抓取的有效(未過期)的表元組數目, 如果是一個索引,那麼就是用這個索引抓取的有效表元組數目 |
| pg_stat_get_tuples_inserted(oid) | bigint | 插入表中的元組數量 |
| pg_stat_get_tuples_updated(oid) | bigint | 在表中已更新的元組數量 |
| pg_stat_get_tuples_deleted(oid) | bigint | 從表中刪除的元組數量 |
| pg_stat_get_blocks_fetched(oid) | bigint | 表或者索引的磁盤塊抓取請求的數量 |
| pg_stat_get_blocks_hit(oid) | bigint | 在緩衝區中找到的表或者索引的磁盤塊請求數目 |
| pg_stat_get_backend_idset() | set of integer | 當前活躍後端 ID 的集合(從 1 到活躍後端的數目)。 參閱文本中的使用樣例。 |
| pg_backend_pid() | integer | 附著在當前會話上的後端進程 ID |
| pg_stat_get_backend_pid(integer) | integer | 給出的後端進程的進程號 |
| pg_stat_get_backend_dbid(integer) | oid | 指定後端進程的數據庫 ID |
| pg_stat_get_backend_userid(integer) | oid | 指定後端進程的用戶 ID |
| pg_stat_get_backend_activity(integer) | text | 後端進程的當前活躍查詢(如果調用者不是超級用戶,或者不是與被查詢的會話同一個用戶, 或者沒有打開 stats_command_string 則為 NULL) |
| pg_stat_get_backend_activity_start(integer) | timestamp with time zone | 指定後端進程當前正在執行的查詢的起始時間(如果當前用戶不是超級用戶,或者 不是與被查詢的會話同一個用戶,或者沒有打開 stats_command_string 則為 NULL) |
| pg_stat_reset() | boolean | 重置所有當前收集的統計。 |
注意: pg_stat_get_db_blocks_fetched 減去 pg_stat_get_db_blocks_hit 就是為該表,索引或者數據庫 發出的 read() 內核調用的數目;不過實際的物理讀取的數目通常比較低, 因為還有內核級的緩衝。
函數 pg_stat_get_backend_idset 提供了一個為每個活躍後端進程生成一行的便捷的方法。 比如,要顯示所有後端的PID和它們的當前查詢:
SELECT pg_stat_get_backend_pid(s.backendid) AS procpid,
pg_stat_get_backend_activity(s.backendid) AS current_query
FROM (SELECT pg_stat_get_backend_idset() AS backendid) AS s;