3 回答

TA貢獻(xiàn)1809條經(jīng)驗(yàn) 獲得超8個(gè)贊
有三種方法可以獲得這種計(jì)數(shù),每種方法都有自己的權(quán)衡。
如果需要真正的計(jì)數(shù),則必須像對每個(gè)表使用的那樣執(zhí)行SELECT語句。這是因?yàn)镻ostgreSQL將行可見性信息保留在行本身,而不是其他任何地方,因此任何準(zhǔn)確的計(jì)數(shù)只能與某個(gè)事務(wù)相關(guān)。您將獲得該事務(wù)在執(zhí)行時(shí)所看到的內(nèi)容的計(jì)數(shù)。您可以自動執(zhí)行此操作以針對數(shù)據(jù)庫中的每個(gè)表運(yùn)行,但您可能不需要那么高的準(zhǔn)確度或者想要等待那么久。
第二種方法指出,統(tǒng)計(jì)信息收集器隨時(shí)跟蹤大約有多少行是“活動的”(未被更新后刪除或廢棄)。在重度活動下,這個(gè)值可能有點(diǎn)偏差,但通常是一個(gè)很好的估計(jì):
SELECT schemaname,relname,n_live_tup FROM pg_stat_user_tables ORDER BY n_live_tup DESC;
這也可以顯示有多少行已死,這本身就是一個(gè)有趣的數(shù)字。
第三種方法是注意系統(tǒng)ANALYZE命令,它定期執(zhí)行autovacuum進(jìn)程,從PostgreSQL 8.3開始更新表統(tǒng)計(jì)信息,也可以計(jì)算行估計(jì)值。你可以像這樣抓住那個(gè):
SELECT nspname AS schemaname,relname,reltuplesFROM pg_class CLEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)WHERE nspname NOT IN ('pg_catalog', 'information_schema') AND relkind='r' ORDER BY reltuples DESC;
哪個(gè)查詢更好用,很難說。通常我根據(jù)是否還有更多有用的信息做出決定,我也想在pg_class或pg_stat_user_tables中使用。出于基本的計(jì)數(shù)目的,只是為了看一般情況有多大,要么都應(yīng)該足夠準(zhǔn)確。

TA貢獻(xiàn)1811條經(jīng)驗(yàn) 獲得超4個(gè)贊
這是一個(gè)解決方案,不需要函數(shù)來獲得每個(gè)表的準(zhǔn)確計(jì)數(shù):
select table_schema, table_name, (xpath('/row/cnt/text()', xml_count))[1]::text::int as row_countfrom ( select table_name, table_schema, query_to_xml(format('select count(*) as cnt from %I.%I', table_schema, table_name), false, true, '') as xml_count from information_schema.tables where table_schema = 'public' --<< change here for the schema you want) t
query_to_xml
將運(yùn)行傳遞的SQL查詢并返回帶有結(jié)果的XML(該表的行數(shù))。然后外部xpath()
將從該xml中提取計(jì)數(shù)信息并將其轉(zhuǎn)換為數(shù)字
派生表并不是必需的,但是xpath()
更容易理解 - 否則query_to_xml()
需要將整個(gè)表傳遞給xpath()
函數(shù)。

TA貢獻(xiàn)1757條經(jīng)驗(yàn) 獲得超7個(gè)贊
要獲得估算,請參閱Greg Smith的回答。
為了得到確切的數(shù)字,到目前為止的其他答案都存在一些問題,其中一些是嚴(yán)重的(見下文)。這是一個(gè)希望更好的版本:
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 LOOP RETURN QUERY EXECUTE format('select cast(%L as text),count(*) from %I.%I', table_name, schema_name, table_name); END LOOP;end$$ language plpgsql;
它將模式名稱作為參數(shù),或者public
如果沒有給出參數(shù)。
要在不修改函數(shù)的情況下使用特定的模式列表或來自查詢的列表,可以在查詢中調(diào)用它,如下所示:
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;
這將產(chǎn)生一個(gè)3列輸出,其中包含模式,表和行數(shù)。
現(xiàn)在這里是這個(gè)函數(shù)避免的其他答案中的一些問題:
表格和模式名稱不應(yīng)在沒有引用的情況下注入可執(zhí)行SQL,無論是使用
quote_ident
更現(xiàn)代的format()
函數(shù)還是使用其%I
格式字符串。否則,一些惡意的人可能將他們的表命名tablename;DROP TABLE other_table
為完全有效的表名。即使沒有SQL注入和有趣的字符問題,表名也可能存在于大小寫不同的變體中。如果一個(gè)表被命名
ABCD
而另一個(gè)被命名abcd
,則SELECT count(*) FROM...
必須使用帶引號的名稱,否則它將跳過ABCD
并計(jì)數(shù)abcd
兩次。該%I
格式的自動執(zhí)行此操作。information_schema.tables
除表格外,還列出自定義復(fù)合類型,即使table_type為'BASE TABLE'
(?。?。因此,我們無法進(jìn)行迭代information_schema.tables
,否則我們會冒險(xiǎn)select count(*) from name_of_composite_type
而且會失敗。OTOHpg_class where relkind='r'
應(yīng)該總能正常工作。COUNT()的類型
bigint
不是int
??赡艽嬖诔^21.5億行的表(雖然對它們運(yùn)行計(jì)數(shù)(*)是個(gè)壞主意)。不需要為函數(shù)創(chuàng)建永久類型以返回具有多個(gè)列的結(jié)果集。
RETURNS TABLE(definition...)
是一個(gè)更好的選擇。
添加回答
舉報(bào)