6

I am looking for a way to approximate the number of rows in a partitioned table. I want to avoid using count(*) because of the size of the data. I tried using this:

SELECT reltuples FROM pg_class WHERE relname = 'my_table_name';

but it always returns zero. I am assuming it's because that table is partitioned.

Is there a way to use pg_class/pg_inherits to get the number of rows in all partitions?

Any ideas are much appreciated!

3
  • Here how to count rows in your db Commented Jun 2, 2015 at 10:41
  • You'll have to find all direct and indirect inheritance (recursive CTE) then sum the stats estimates for each. Commented Jun 2, 2015 at 10:56
  • Thanks! I found a way to use inheritance, posted it in an answer. Commented Jun 2, 2015 at 11:05

5 Answers 5

12

Simple way, if the child partitions follow a naming scheme:

SELECT schemaname,relname,n_live_tup
FROM pg_stat_user_tables
where relname like 'my_table_%'
ORDER BY relname DESC ;
Sign up to request clarification or add additional context in comments.

Comments

5

Found a way to do this:

            SELECT
                SUM(child.reltuples)    AS number_of_records_all_partitions
            FROM pg_inherits
                JOIN pg_class parent            ON pg_inherits.inhparent = parent.oid
                JOIN pg_class child             ON pg_inherits.inhrelid   = child.oid
                JOIN pg_namespace nmsp_parent   ON nmsp_parent.oid  = parent.relnamespace
                JOIN pg_namespace nmsp_child    ON nmsp_child.oid   = child.relnamespace
            WHERE parent.relname = 'my_table_name';

I am also using the system ANALYZE command, and the parent/child relationship between a table and it's partitions.

1 Comment

This is pretty good! I'd love to make this a sub-select or a join of some sort that works even if the table isn't inherited.
3

If you want to handle multiple levels of inheritance correctly (c inherits b inherits a) then you need a recursive query:

WITH RECURSIVE tree AS
(
  SELECT i.inhrelid AS oid
  FROM pg_inherits i
    JOIN pg_class base_t ON i.inhparent = base_t.oid
    JOIN pg_namespace base_ns ON base_t.relnamespace = base_ns.oid
  WHERE base_ns.nspname = 'base_schema' 
    AND base_t.relname = 'base_table_name'

  UNION ALL

  SELECT i.inhrelid AS oid
  FROM pg_inherits i
    JOIN tree b ON i.inhparent = b.oid
    JOIN pg_class cl on cl.oid = i.inhrelid
)
SELECT sum(tbl.reltuples)
FROM tree tr
  JOIN pg_class tbl ON tr.oid = tbl.oid;

2 Comments

Can that be the case in partitioning though?
@Sanuye: theoretically, yes.
1

This one worked for me for a hash partitioned table:

SELECT sum(reltuples)::int8
FROM pg_catalog.pg_class
WHERE relispartition = true
    AND reltype != 0 -- ignore indexes

Comments

0

I'd like @a_horse_with_no_name answer and plus it, but recursive query may be much simpler:

WITH RECURSIVE tree AS (
  SELECT i.inhrelid AS oid
  FROM pg_inherits i
  WHERE i.inhparent = 'scheme.my_table_name'::regclass
UNION ALL
  SELECT i.inhrelid AS oid
  FROM pg_inherits i
    JOIN tree b ON i.inhparent = b.oid
)
SELECT sum(tbl.reltuples)
FROM tree tr
  JOIN pg_class tbl ON tr.oid = tbl.oid;

That may be also transformed into a more generic variant for all tables, ready for join (including unpartitioned):

    WITH RECURSIVE tables_tree AS ( -- See https://stackoverflow.com/questions/30592826/postgres-approximate-number-of-rows-in-partitioned-tables/68958004#68958004
      SELECT oid AS oid, oid as parent_oid
      FROM pg_class i
    UNION ALL
      SELECT i.inhrelid AS oid, t.parent_oid
      FROM pg_inherits i
        JOIN tables_tree t ON i.inhparent = t.oid
    ), tables_total_size AS (
        SELECT sum(tbl.reltuples) as estimated_table_rows_sum, t.parent_oid
        FROM tables_tree t
          JOIN pg_class tbl ON t.oid = tbl.oid
        GROUP BY t.parent_oid
    )
    SELECT *, parent_oid::regclass as table_name
    FROM tables_total_size

DB-fiddle

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.