postgresql 讀書會 一期 系統管理的一些script 3

表的狀態例如當前有多少live rows , index scans   等等都能幫助定義空和無用的表,根據一些基本的查詢語句就能得到有效的驗證,  pg_stat_user_tables 提供了這方面的功能和信息.

對於找到無用的index的問題,有兩個點可以被用到, 第一個技術是找到索引重複的, 第二個是基於索引被訪問到的狀態.

WITH index_info AS

(SELECT pg_get_indexdef(indexrelid) AS index_def, indexrelid::regclass

index_name , indrelid::regclass table_name, array_agg(attname) AS index_att 

FROM  pg_index i 

JOIN pg_attribute a ON i.indexrelid = a.attrelid

GROUP BY pg_get_indexdef(indexrelid), indrelid, indexrelid

)

SELECT DISTINCT

CASE WHEN a.index_name > b.index_name THEN a.index_def

ELSE b.index_def END AS index_def,

CASE WHEN a.index_name > b.index_name THEN

a.index_name ELSE b.index_name END AS index_name,

CASE WHEN a.index_name > b.index_name THEN b.index_def

ELSE a.index_def END AS overlap_index_def,

CASE WHEN a.index_name > b.index_name THEN b.index_def

ELSE a.index_def END AS overlap_index_name,

a.table_name

FROM

index_info a INNER 

JOIN index_info b ON a.index_name != b.index_name

AND a.table_name = b.table_name AND a.index_att && b.index_att ;

上面這段尋找INDEX 重複的主要是基於INDEX  NAME 和創建INDEX語句的比對生成的. 所以在給出結果後,還需要人工來進行更細緻的比對,不能進行直接的重複索引的清理.

另外在日常工作中經常有由於程序或相關人員誤操作導致的一張表中的重複數據的問題.下圖的表中name 是不應該重複的,現在我們要在已經有錯誤數據的表上加唯一索引,由於有重複的數據則是不能進行的,如果這是在別的數據庫上處理上要比PG麻煩,PG 本身具有ctid的物理屬性, 所以藉由這個屬性就可以簡單的清理重複的數據.

如果保留第一次輸入的重複數據的第一天就使用min 如果是保留左後一次的輸入,就選擇max, 這裏處理這個功能PG還是比較方便的.

對於當前的PG中語句之間的鎖定,主要在於獨佔式的訪問,access exclusive , 例如改動表的物理結構, alter ,drop , truncate ,vacuum full, cluster ,reindex 等等. 另一種語句之間的等待,有的時候一個語句會等待另一個語句很長時間,主要是locked 語句沒有commited.

SELECT
lock1.pid as locked_pid,
stat1.usename as locked_user,
stat1.query as locked_statement,
stat1.state as state,
stat2.query as locking_statement,
stat2.state as state,
now() - stat1.query_start as locking_duration,
lock2.pid as locking_pid,
stat2.usename as locking_user
FROM pg_catalog.pg_locks lock1
JOIN pg_catalog.pg_stat_activity stat1 on lock1.pid = stat1.pid
JOIN pg_catalog.pg_locks lock2 on
(lock1.locktype,lock1.database,lock1.relation,
lock1.page,lock1.tuple,lock1.virtualxid,
lock1.transactionid,lock1.classid,lock1.objid,
lock1.objsubid) IS NOT DISTINCT FROM
(lock2.locktype,lock2.DATABASE,
lock2.relation,lock2.page,
lock2.tuple,lock2.virtualxid,
lock2.transactionid,lock2.classid,
lock2.objid,lock2.objsubid)
JOIN pg_catalog.pg_stat_activity stat2 on lock2.pid
= stat2.pid
WHERE NOT lock1.granted AND lock2.granted;

上面的語句可以查出類似的情況,幫助相關人員分析當前的PG的語句鎖的情況.

下面就是查出兩個語句15423 阻擋了 15226的執行

然後你就可以選擇到底要刪除那個語句是被鎖的還是引起鎖的.  通過 select pg_terminate_backend(pid) 將連接切斷. 

最後還有一個問題可能會被問及, 關於VIEW  和那些表有關係的問題, 例如問及現在的VIEW 都和那些表之間有關係,這並不是一個很容易回答的問題,尤其一個VIEW中有多個表參與合成.  下面的語句就會將VIEW 和表之間的關係打印出來.

SELECT view_schema,view_name parent, table_schema, table_name FROM
information_schema.view_table_usage WHERE view_name LIKE '_' order by
view_name;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章