記一次postgresql數據庫函數執行問題
阿新 • • 發佈:2018-03-02
absolute btree 服務器 -m ans ica ret cpu integer
1、func_init.sql 入參為一個int類型number,根據傳入的number做循環,循環調用func_process.sql。
2、func_process.sql 沒有入參,出參為完成狀態值integer,裏面共分五步: a)、查詢macInfo表,得到一條state=0的mac值【該表有65w條數據,且只有mac和state兩個字段,mac為主鍵】
c)、生成各個sequence(大概12個)
d)、組裝12個insert語句(12張表)【這裏用到了第a步裏得到的mac】
e)、更新macInfo表,將mac值對應的數據的state改為1。
3、func_uuid.sql通過plpythonu語言編寫,生成UUID,與sql無關。
檢查postgresql所在服務器,發現當執行函數的時候,會將一個cpu占到90%,占所有cpu的6%。當這個函數執行完成時,幾乎不占,因此可以確定是這個函數造成的。
2、經過排除,發現是第a步,查詢mac非常慢,每次耗時100ms。原本耗時是7ms。
猜想macInfo表中state當時值分布中為0的已經很少,都是為1的,且沒有索引導致查詢慢。
5、既然索引沒用,那麽我刪掉state為1的數據,只留下15000條state為0的數據。
7、還原macinfo表,將數據還原成最初形式。再次執行。速度還是很慢,1000條500s。
五、小結發現就是macinfo表的原因,而且必定能重現。
一、函數說明:
首先編寫了三個函數:func_init.sqlfunc_process.sqlfunc_uuid.sql1、func_init.sql 入參為一個int類型number,根據傳入的number做循環,循環調用func_process.sql。
...
BEGIN
FOR i IN 1..num LOOP
SELECT func_process.sql() INTO counts;
if counts = 0 then return ‘mac地址已使用完‘;
end if;
end LOOP;
...
12 1...
2BEGIN
3
4FOR i IN 1..num LOOP5
6 SELECT func_process.sql() INTO counts;
7
8 if counts = 0 then return ‘mac地址已使用完‘;
9 end if;
10
11end LOOP;
12...
2、func_process.sql 沒有入參,出參為完成狀態值integer,裏面共分五步: a)、查詢macInfo表,得到一條state=0的mac值【該表有65w條數據,且只有mac和state兩個字段,mac為主鍵】
select mac from macInfo where state = 0 limit 1;
1 1select mac from macInfo where state = 0 limit 1;
b)、調用func_uuid.sql,得到uuid【該方法通過plpythonu語言編寫,生成UUID】c)、生成各個sequence(大概12個)
d)、組裝12個insert語句(12張表)【這裏用到了第a步裏得到的mac】
e)、更新macInfo表,將mac值對應的數據的state改為1。
3、func_uuid.sql通過plpythonu語言編寫,生成UUID,與sql無關。
二、postgresql函數問題:
單個函數就是一個事物,無法主動提交事物。也就是說,我func_init傳入的值是多少,那麽必須這些全部處理完才會提交事務,中途無法主動提交。三、前提如下:
由於一開始沒有特別的考慮性能問題,使用了insert into,而不是copy。macInfo表裏state沒有建立索引。一開始macInfo表的所有state都為0。寫了一個python腳本,在服務器循環調用func_init(10000),調用了65次,用來規避postgresql無法主動提交事務問題。四、發生的問題以及排查
1、一開始跑的時候,前幾次func_init(10000),也就是執行10000次func_process,耗時135s。當func_init(10000)跑到第60次的時候,發現耗時非常久,需要20分鐘多。也就是速度慢了10倍。檢查postgresql所在服務器,發現當執行函數的時候,會將一個cpu占到90%,占所有cpu的6%。當這個函數執行完成時,幾乎不占,因此可以確定是這個函數造成的。
2、經過排除,發現是第a步,查詢mac非常慢,每次耗時100ms。原本耗時是7ms。
猜想macInfo表中state當時值分布中為0的已經很少,都是為1的,且沒有索引導致查詢慢。
>> select "state", "count"("state") from macinfo GROUP BY state;
>>
state count
1 641153
0 15000
5 1>> select "state", "count"("state") from macinfo GROUP BY state;
2>>
3state count
41 641153
50 15000
3、因此為state加上索引。CREATE INDEX "idx_macinfo_state" ON "usr"."macinfo" USING BTREE ("state");
1 1CREATE INDEX "idx_macinfo_state" ON "usr"."macinfo" USING BTREE ("state");
4、再次執行,發現速度還是很慢,幾乎沒有改變。5、既然索引沒用,那麽我刪掉state為1的數據,只留下15000條state為0的數據。
create table usr.macinfo_copy as select * from usr.macinfo;
DELETE FROM usr.macinfo where "state" <> 0;
1 1create table usr.macinfo_copy as select * from usr.macinfo;
2DELETE FROM usr.macinfo where "state" <> 0;
6、再次執行,本次執行了1000條,發現耗時680s,換算成10000條也就是 10分鐘多點。相比快了一倍,但是和最開始比還是慢了5倍。因此該方法還是不行7、還原macinfo表,將數據還原成最初形式。再次執行。速度還是很慢,1000條500s。
五、小結發現就是macinfo表的原因,而且必定能重現。
記一次postgresql數據庫函數執行問題