閱讀242 返回首頁    go 阿裏雲 go 技術社區[雲棲]


PostgreSQL 妙用explain Plan Rows快速估算結果集數量

https://people.planetpostgresql.org/dfetter/index.php?/archives/80-Approximate-Counts.html
通過這種方法,我們可以快速的估算一個表,視圖的記錄數,當然也包括帶條件的查詢中,最終結果的返回集。
例如:
postgres=# EXPLAIN (FORMAT JSON) SELECT 1 FROM  t limit 1;
                QUERY PLAN                 
-------------------------------------------
 [                                        +
   {                                      +
     "Plan": {                            +
       "Node Type": "Limit",              +
       "Startup Cost": 0.00,              +
       "Total Cost": 0.01,                +
       "Plan Rows": 1,                    +
       "Plan Width": 0,                   +
       "Plans": [                         +
         {                                +
           "Node Type": "Seq Scan",       +
           "Parent Relationship": "Outer",+
           "Relation Name": "t",          +
           "Alias": "t",                  +
           "Startup Cost": 0.00,          +
           "Total Cost": 14425.00,        +
           "Plan Rows": 1000000,          +
           "Plan Width": 0                +
         }                                +
       ]                                  +
     }                                    +
   }                                      +
 ]
(1 row)

postgres=# EXPLAIN (FORMAT JSON) SELECT 1 FROM  t;
           QUERY PLAN           
--------------------------------
 [                             +
   {                           +
     "Plan": {                 +
       "Node Type": "Seq Scan",+
       "Relation Name": "t",   +
       "Alias": "t",           +
       "Startup Cost": 0.00,   +
       "Total Cost": 14425.00, +
       "Plan Rows": 1000000,   +
       "Plan Width": 0         +
     }                         +
   }                           +
 ]
(1 row)

通過函數,將Plan Rows轉換成輸出:
postgres=# CREATE OR REPLACE FUNCTION countit(name,name)             
RETURNS float4         
LANGUAGE plpgsql AS        
$$DECLARE             

    v_plan json;              

BEGIN                    

    EXECUTE format('EXPLAIN (FORMAT JSON) SELECT 1 FROM %I.%I', $1,$2)

        INTO v_plan;                                                                     

    RETURN v_plan #>> '{0,Plan,"Plan Rows"}';

END;

$$;
CREATE FUNCTION
使用這種方法就可以快速評估所有表和視圖的行數了。
postgres=# SELECT
    relname AS "table",
    CASE WHEN relkind = 'r'
        THEN reltuples
        ELSE countit(n.nspname,relname)
    END AS "approximate_count"
FROM
    pg_catalog.pg_class c
JOIN
    pg_catalog.pg_namespace n ON (
        c.relkind IN ('r','v') AND
        c.relnamespace = n.oid                                                         
    );

另外,還有一種更加簡便的方法是輸出pg_class.reltuples,但是這個字段的值analyze(包括auto analyze)後才有的,
而使用explain 的方法,還可以適用沒有統計信息的情況。

[參考]
https://people.planetpostgresql.org/dfetter/index.php?/archives/80-Approximate-Counts.html

最後更新:2017-04-01 13:37:08

  上一篇:go PostgreSQL 大實例的備份方案之一
  下一篇:go MongoDB請求處理流程