1. 程式人生 > 其它 >postgresql 資料庫 update更新慢的原因(已解決)

postgresql 資料庫 update更新慢的原因(已解決)

這幾天 發現一條update的更新語句 (大約140000條資料) 竟然運行了一個小時還沒有完成
下面是我的幾點解決方案
我的update 語句 是從一個臨時表更新值到另一個正式表
因為具體資料需要保密,我就不截圖了 只說說大體思路,與方法

1.檢視語句是否有問題

複製倆個一模一樣的表 和資料 手動執行語句 發現不到一分鐘就執行成功了 這樣就可以確認語句沒有問題

2.查詢影響updata的因素


我的第一反應是不是有鎖 有鎖的情況會導致等待或者死鎖

查詢鎖

select w1.pid as 等待程序,
w1.mode as 等待鎖模式,
w2.usename as 等待使用者,
w2.query as 等待會話,
b1.pid as 鎖的程序,
b1.mode 鎖的鎖模式,
b2.usename as 鎖的使用者,
b2.query as 鎖的會話,
b2.application_name 鎖的應用,
b2.client_addr 鎖的IP地址,
b2.query_start 鎖的語句執行時間
from pg_locks w1
join pg_stat_activity w2 on w1.pid=w2.pid
join pg_locks b1 on w1.transactionid=b1.transactionid and w1.pid!=b1.pid
join pg_stat_activity b2 on b1.pid=b2.pid
where not w1.granted;

  

SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE pid='13828'

查詢到有鎖 把鎖程序殺掉 重啟服務 繼續跟蹤 發現5分鐘後 又出現鎖了 反覆試了幾次發現跟鎖沒有關係

3.查詢引數

首先看的的 是shared_buffers 引數,發現也沒有問題

4.收縮表 VACUUM

查詢資料程序時,發現自動收縮 也執行10分鐘還沒好 就查詢表收縮的情況

用於伺服器監控,可查詢程序,時間消耗與鎖相關

SELECT 

C.relname 物件名稱,
l.locktype 可鎖物件的型別,
l.pid 程序id,
l.MODE 持有的鎖模式,
l.GRANTED 是否已經對鎖進行授權,
l.fastpath,
psa.datname 資料庫名稱,
psa.usesysid 使用者id,
psa.usename 使用者名稱稱,
psa.application_name 應用程式名稱,
psa.client_addr 連線的IP地址,
psa.client_port 連線使用的TCP埠號,
psa.backend_start 程序開始時間,
psa.xact_start 事務開始時間,
psa.query_start 事務執行此語句時間,
psa.state_change 事務狀態改變時間,
psa.wait_event_type 等待事件型別,
psa.wait_event 等待事件,
psa.STATE 查詢狀態,

backend_xid 事務是否有寫入操作,
backend_xmin 是否執事務快照,

psa.query 執行語句,
now( ) 
- query_start 持續時間 FROM pg_locks l INNER JOIN pg_stat_activity psa ON ( psa.pid = l.pid ) LEFT OUTER JOIN pg_class C ON ( l.relation = C.oid ) -- where l.relation = 'tb_base_apparatus'::regclass where relkind ='r' ORDER BY query_start asc



查詢是否到達自動清理的表

SELECT
    c.relname 表名,
    (current_setting(
'autovacuum_analyze_threshold')::NUMERIC(12,4))+(current_setting('autovacuum_analyze_scale_factor')::NUMERIC(12,4))*reltuples AS 自動分析閾值, (current_setting('autovacuum_vacuum_threshold')::NUMERIC(12,4))+(current_setting('autovacuum_vacuum_scale_factor')::NUMERIC(12,4))*reltuples AS 自動清理閾值, reltuples::DECIMAL(19,0) 活元組數, n_dead_tup::DECIMAL(19,0) 死元組數 FROM pg_class c LEFT JOIN pg_stat_all_tables d ON C.relname = d.relname WHERE c.relname LIKE'tb%' AND reltuples > 0 AND n_dead_tup > (current_setting('autovacuum_analyze_threshold')::NUMERIC(12,4))+(current_setting('autovacuum_analyze_scale_factor')::NUMERIC(12,4))*reltuples;

然後發現死元祖太多
然後我手動收縮了這個表 之後更新的就快了

VACUUM FULL VERBOSE 表名;
VACUUM FULL VERBOSE ANALYZE 表名;
為人:謙遜、激情、博學、審問、慎思、明辨、 篤行
學問:紙上得來終覺淺,絕知此事要躬行
為事:工欲善其事,必先利其器。
態度:道阻且長,行則將至;行而不輟,未來可期
轉載請標註出處!