2016-07-31 44 views
2

下面是檢查PostgreSQL數據庫中所有表的真實數量的一個很好的函數。我發現它here如何更新函數中的EXECUTE格式塊的結果(PostgreSQL)

從我的本地測試看來,函數只有在完成100個表的所有計數後才返回所有結果。

我想讓它更實用。如果我們可以在表格結束後立即保存每個表格的計數結果,那麼我們可以檢查所有計數作業的進度而不是等待結束。

我想如果我可以在完成第一個表格後立即更新這個函數的結果,那對我的需求來說是非常好的。

你能告訴我如何在該函數完成第一個表的計數後將結果更新到表中嗎?

CREATE FUNCTION rowcount_all(schema_name text default 'public') 
    RETURNS table(table_name text, cnt bigint) as 
$$ 
declare 
table_name text; 
begin 
    for table_name in SELECT c.relname FROM pg_class c 
    JOIN pg_namespace s ON (c.relnamespace=s.oid) 
    WHERE c.relkind = 'r' AND s.nspname=schema_name 
    ORDER BY c.relname 
    LOOP 
    RETURN QUERY EXECUTE format('select count(*) from %I.%I', 
     table_name, schema_name, table_name); 
    END LOOP; 
end 
$$ language plpgsql; 

-- Query 

WITH rc(schema_name,tbl) AS (
    select s.n,rowcount_all(s.n) from (values ('schema1'),('schema2')) as s(n) 
) 
SELECT schema_name,(tbl).* FROM rc; 

更新

我決定用一個shell腳本下面作爲後臺進程運行的功能。該函數將生成一個處理日誌文件,以便我可以檢查當前進程。

回答

1

我認爲你的想法很好,但我也認爲它不會在PostgreSQL上「開箱即用」。我絕不是這方面的專家,但是MVCC在PostgreSQL上工作的方式,基本上是將所有的DML都用作臨時空間,然後如果一切按預期工作,它就會把它全部移到最後。

這有很多好處,最值得注意的是,當有人更新表時,它並不妨礙其他人從這些相同的表中查詢。

如果這是Oracle,我認爲您可以在存儲過程中使用commit,來完成此操作,但這不是Oracle。公平地說,Oracle不允許截斷在PostgreSQL的方式下在存儲過程中回滾,所以有要求和要求。

再次,我不是專家,所以如果我弄糟了一兩個細節,請隨時糾正我。

所以,回到解決方案。其中一種方法是將服務器設置爲遠程服務器。像這樣的東西會工作:

CREATE SERVER pgprod 
FOREIGN DATA WRAPPER dblink_fdw 
OPTIONS (dbname 'postgres', host 'localhost', port '5432'); 

假設你有一個存儲表和計數的表:

create table table_counts (
    table_name text not null, 
    record_count bigint, 
    constraint table_counts_pk primary key (table_name) 
); 

如果不是你希望看到這些結果,因爲它們發生,像這樣的工作,爲一個單一的模式。這是很容易使這一切的模式,所以這是爲了說明:

CREATE or replace FUNCTION rowcount_all(schema_name text) 
    returns void as 
$$ 
declare 
rowcount integer; 
tablename text; 
begin 
    for tablename in SELECT c.relname FROM pg_class c 
    JOIN pg_namespace s ON (c.relnamespace=s.oid) 
    WHERE c.relkind = 'r' AND s.nspname=schema_name 
    ORDER BY c.relname 
    LOOP 
    EXECUTE 'select count(*) from ' || schema_name || '.' || tablename into rowcount; 
    insert into table_counts values (schema_name || '.' || tablename, rowcount) 
    on conflict (table_name) do 
    update set record_count = rowcount; 
    END LOOP; 
end 
$$ language plpgsql; 

(這預示9.5或更高 - 如果不是,手推出自己的upsert)。

不過,既然你要實時更新表,然後你可以把同樣的UPSERT成DBLINK表達:

perform dblink_exec('pgprod', ' 
     << your upsert statement here >> 
    '); 

當然的DBLINK內的SQL的格式是現在有點額外的棘手,但是一旦你掌握了它的優勢,你可以在後臺運行該功能,並在運行時查詢該表以查看動態結果。

我會考慮實時掌握信息的真實性。

+0

精彩的方法。你的意思是沒有DBlink實現,我不能動態查詢table_counts,因爲它會在所有計數作業完成後提交。 – Sigularity

+0

我的外部應用程序可以每10秒查詢table_counts表,所以我想不需要實現DBlink? – Sigularity

+0

我可能會問函數中的'自主事務'。功能正在工作時,我無法查詢表格。 – Sigularity

相關問題