Как получить общее количество строк и столбец max (timestamp) в списке выбора для всей таблицы в конкретной схеме

У нас есть база данных Только для чтения на основе Postgres. в этом у нас есть 52 таблицы по одной схеме.

Мы пытаемся вывести количество строк и столбец max (timestamp) для всех таблиц в одной схеме.

Окружающая среда:

PostgreSQL 8.2.15 (база данных Greenplum 4.2.0 сборка 1) (HAWQ 1.3.0.2 сборка 14421) на x86_64-unknown-linux-gnu, скомпилированная GCC gcc (GCC) 4.4.2 скомпилированная

Мы примерили:

SELECT 
  nspname AS schemaname,relname,reltuples,max(time)
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE 
  nspname NOT IN ('pg_catalog', 'information_schema') AND
  relkind='r' 
ORDER BY reltuples DESC;

В этом запросе мы получили столбец количества строк, но все еще не достигнуто значение max(timestamp) для всей таблицы.

Любая помощь в этом будет высоко оценена?


person NEO    schedule 26.05.2016    source источник
comment
Привет, vickps. Какой формат отметки времени вы используете, например, время с часовым поясом или без него?   -  person    schedule 26.05.2016
comment
Использование метки времени без часового пояса   -  person NEO    schedule 26.05.2016


Ответы (2)


С помощью этого запроса вы получаете доступ к статистике базы данных, которая не является на 100% точной и может отсутствовать или устареть в зависимости от ваших процессов сбора статистики.

Чтобы получить количество строк для списка таблиц, вы должны просмотреть каждую из этих таблиц. Однако вы можете использовать pg_relation_size(), чтобы получить представление о размере таблицы в байтах, и эта функция не требует сканирования таблицы.

Если ваш список таблиц статичен, вы можете обойтись без такого запроса:

select 'table1', count(*), max(time) from table1
union all
select 'table2', count(*), max(time) from table2
union all
...
select 'table52', count(*), max(time) from table52;

Это решение не является гибким, так как если список таблиц изменился, вам нужно переписать запрос.

Второй вариант — сгенерировать этот запрос и выполнить его вручную:

select string_agg(query, ' union all ') as query
    from (
        select 'select ''' || n.nspname || '.' || c.relname || ''', count(*), max(time) from ' || n.nspname || '.' || c.relname as query
            from pg_namespace as n, pg_class as c
            where n.oid = c.relnamespace
                and n.nspname = 'my_schema'
        ) as q;

Это более гибко, однако второй запрос следует выполнять вручную.

И, наконец, ваш последний вариант - написание функции для этого:

create or replace function table_sizes (schemaname varchar) returns setof record as $BODY$
declare
    r record;
    t varchar;
begin
    for t in execute $$
        select n.nspname || '.' || c.relname
            from pg_namespace as n, pg_class as c
            where n.oid = c.relnamespace
                and c.relkind = 'r'
                and n.nspname = '$$ || schemaname || $$'$$
    loop
        execute 'select ''' || t || '''::varchar, count(*), max(time) from ' || t
            into r;
        return next r;
    end loop;
    return;
end;
$BODY$ language plpgsql volatile;

select * from table_sizes('public') t(tablename varchar, rowcount bigint, maxtime time);
person 0x0FFF    schedule 26.05.2016
comment
когда я выполняю функцию здесь. получение следующего :: prod=# select * from table_sizes('schemaname') t(tablename varchar, rowcount bigint, maxtime time); ОШИБКА: в RETURN NEXT CONTEXT указан неправильный тип записи: функция PL/pgSQL table_sizes, строка 14 при возврате next prod=# - person NEO; 26.05.2016
comment
это означает, что ваш оператор выбора не соответствует возвращаемому типу данных. Каков тип данных поля времени? Он должен совпадать с тем, что указан в запросе select. - person 0x0FFF; 26.05.2016
comment
временная метка без часового пояса - person NEO; 26.05.2016
comment
понятно . я изменил его на метку времени. запрос выполнен. Благодаря тонну . функция классная. - person NEO; 26.05.2016
comment
Кроме того, для больших таблиц я рекомендую работать с pg_relation_type вместо подсчета строк. Кроме того, max(time) можно хранить в таблице метаданных, которая будет обновляться в той же транзакции, что и основные таблицы, таким образом, нет необходимости вычислять ее вручную. - person 0x0FFF; 26.05.2016

Вот еще несколько шагов, которые нужно сделать:

В psql выполните следующие шаги

\o count_per_schema.sql
select 'select count(*)as '||c.relname||', max(time) from ' || n.nspname || '.' || c.relname || ';' as " " from pg_namespace as n, pg_class as c where n.oid = c.relnamespace and c.relkind='r' and n.nspname = 'schema_name';
\o
\i count_per_schema.sql

\o перенаправит результат на указанный вами filename. Например, count_per_schema.sql и \i будут выполнять все запросы из файла.

Вот что я сделал на сервере. Я не выбрал максимальное (время).

yogesh=# \o count_per_schema.sql
yogesh=# select 'select count(*)as '||c.relname||' from ' || n.nspname || '.' || c.relname || ';' as " " from pg_namespace as n, pg_class as c where n.oid = c.relnamespace and c.relkind='r' and n.nspname = 'public';
yogesh=# \o
yogesh=# \i count_per_schema.sql

 heap1
-------
 20000
(1 row)
 test
-------
     4
(1 row)
 users
-------
     0
(1 row)
 skew_demo
-------
 10609
(1 row)
person pgyogesh    schedule 27.05.2016
comment
Преимущество этого в том, что вы можете удалять записи для таблиц, которые вам не нужны, из выходного файла. - person pgyogesh; 28.05.2016