亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在PostgreSQL中發現表的行數的快速方法

在PostgreSQL中發現表的行數的快速方法

慕萊塢森 2019-12-12 14:20:38
我需要知道表中的行數以計算百分比。如果總計數大于某個預定義常數,我將使用該常數值。否則,我將使用實際的行數。我可以用SELECT count(*) FROM table。但是,如果我的常數值為500,000,并且表中有5,000,000,000行,則對所有行進行計數將浪費大量時間。一旦超過我的恒定值,是否可以停止計數?只要行數低于給定的限制,我就需要確切的行數。否則,如果計數超出限制,我將改用限制值,并希望盡快給出答案。像這樣:SELECT text,count(*), percentual_calculus()  FROM token  GROUP BY text  ORDER BY count DESC;
查看完整描述

3 回答

?
拉莫斯之舞

TA貢獻1820條經驗 獲得超10個贊

在PostgreSQL中,對大表中的行進行計數是很慢的。為了獲得準確的數字,由于MVCC的性質,它必須對行進行完整計數。有一種方法來大大加快這如果計數也沒有必須要確切喜歡它似乎是在你的情況。


而不是獲得確切的計數(大表速度慢):


SELECT count(*) AS exact_count FROM myschema.mytable;

您會得到如下估算值(非??欤?/p>


SELECT reltuples::bigint AS estimate FROM pg_class where relname='mytable';

估算的接近程度取決于您是否運行ANALYZE足夠。通常非常接近。

請參閱PostgreSQL Wiki FAQ。

或用于count(*)性能的專用Wiki頁面。


更好了

PostgreSQL的維基文章的是一個有點草率。它忽略了一個數據庫中可能存在多個具有相同名稱的表的可能性-處于不同的模式。要說明這一點:


SELECT c.reltuples::bigint AS estimate

FROM   pg_class c

JOIN   pg_namespace n ON n.oid = c.relnamespace

WHERE  c.relname = 'mytable'

AND    n.nspname = 'myschema'

還是更好

SELECT reltuples::bigint AS estimate

FROM   pg_class

WHERE  oid = 'myschema.mytable'::regclass;

更快,更簡單,更安全,更優雅。請參閱《對象標識符類型》手冊。


to_regclass('myschema.mytable')在Postgres 9.4+中使用可避免無效表名的例外情況:


如何檢查給定架構中是否存在表



TABLESAMPLE SYSTEM (n) 在Postgres 9.5+

SELECT 100 * count(*) AS estimate FROM mytable TABLESAMPLE SYSTEM (1);

就像@a_horse commented一樣,SELECT如果pg_class由于某些原因當前的統計信息不足,則為該命令新添加的子句可能會很有用。例如:


沒有autovacuum運行。

大INSERT或DELETE。

TEMPORARY表格(未被涵蓋autovacuum)。

這只會查看隨機的n%(1在示例中)選擇的塊并計算其中的行。您可以選擇更大的樣本來增加成本,并減少誤差。準確性取決于更多因素:


行大小分布。如果給定的塊恰好比平常的行寬,則計數比平常的低,等等。

死元組或FILLFACTOR每個塊占用空間。如果整個表分布不均,則估計值可能會不正確。

一般舍入錯誤。

在大多數情況下,來自的估計pg_class會更快,更準確。


回答實際問題

首先,我需要知道該表中的行數,如果總計數大于某個預定義常量,


以及是否...


...在計數超過我的常數值時是可能的,它將停止計數(而不是等待完成計數以告知行計數更大)。


是。您可以將子查詢與結合使用LIMIT:


SELECT count(*) FROM (SELECT 1 FROM token LIMIT 500000) t;

Postgres 實際上停止計數超過給定的限制,您將獲得多達n行(在本示例中為500000)的精確和當前計數,否則為n。但是,速度不及中的估算速度。pg_class


查看完整回答
反對 回復 2019-12-12
?
慕蓋茨4494581

TA貢獻1850條經驗 獲得超11個贊

我通過運行在postgres應用程序中執行了一次:


EXPLAIN SELECT * FROM foo;

然后使用正則表達式或類似的邏輯檢查輸出。對于簡單的SELECT *,輸出的第一行應如下所示:


Seq Scan on uids  (cost=0.00..1.21 rows=8 width=75)

您可以將該rows=(\d+)值用作將要返回的行數的粗略估計,然后僅SELECT COUNT(*)在估計值小于閾值的1.5倍(或您認為對應用程序有意義的任何數目)時才進行實際計算。


根據查詢的復雜程度,此數字可能會越來越少。實際上,在我的應用程序中,當我們添加聯接和復雜條件時,它變得如此不準確,以至于完全不值錢,甚至不知道在100的冪內將返回多少行,因此我們不得不放棄該策略。


但是,如果您的查詢足夠簡單,Pg可以在合理的誤差范圍內預測它將返回多少行,那么它可能對您有用。


查看完整回答
反對 回復 2019-12-12
?
守著星空守著你

TA貢獻1799條經驗 獲得超8個贊

在Oracle中,您可以rownum用來限制返回的行數。我猜想其他SQL中也存在類似的構造。因此,對于您給出的示例,可以將返回的行數限制為500001,count(*)然后應用a :


SELECT (case when cnt > 500000 then 500000 else cnt end) myCnt

FROM (SELECT count(*) cnt FROM table WHERE rownum<=500001)


查看完整回答
反對 回復 2019-12-12
  • 3 回答
  • 0 關注
  • 2263 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號