Existem três maneiras de obter esse tipo de contagem, cada uma com suas próprias vantagens e desvantagens.
Se você deseja uma contagem verdadeira, é necessário executar a instrução SELECT como a que você usou em cada tabela. Isso ocorre porque o PostgreSQL mantém as informações de visibilidade da linha na própria linha, e não em nenhum outro lugar; portanto, qualquer contagem precisa pode ser relativa apenas a alguma transação. Você está obtendo uma contagem do que essa transação vê no momento em que é executada. Você pode automatizar isso para executar em todas as tabelas do banco de dados, mas provavelmente não precisa desse nível de precisão ou deseja esperar tanto tempo.
A segunda abordagem observa que o coletor de estatísticas rastreia aproximadamente quantas linhas estão "ativas" (não excluídas ou obsoletas por atualizações posteriores) a qualquer momento. Esse valor pode ser um pouco baixo em atividades pesadas, mas geralmente é uma boa estimativa:
SELECT schemaname,relname,n_live_tup
FROM pg_stat_user_tables
ORDER BY n_live_tup DESC;
Isso também pode mostrar quantas linhas estão mortas, o que é um número interessante para monitorar.
A terceira maneira é observar que o comando ANALYZE do sistema, que é executado pelo processo de autovacuum regularmente a partir do PostgreSQL 8.3 para atualizar as estatísticas da tabela, também calcula uma estimativa de linha. Você pode pegar esse assim:
SELECT
nspname AS schemaname,relname,reltuples
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;
Qual dessas consultas é melhor usar é difícil dizer. Normalmente, tomo essa decisão com base em informações mais úteis que também quero usar dentro de pg_class ou dentro de pg_stat_user_tables. Para propósitos básicos de contagem, apenas para ver em que medida as coisas são grandes em geral, devem ser suficientemente precisas.
with tbl as (SELECT table_schema,table_name FROM information_schema.tables where table_name not like 'pg_%' and table_schema in ('public')) select table_schema, table_name, (xpath('/row/c/text()', query_to_xml(format('select count(*) as c from %I.%I', table_schema, table_name), false, true, '')))[1]::text::int as rows_n from tbl ORDER BY 3 DESC;
n_live_tup
? Meu banco de dados Redshift não possui essa coluna. É um derivado do Postgres 8.0.2.pg_stat_user_tables
) retornou principalmente zerosn_live_tup
para mim porqueANALYZE
nunca havia sido executada. Em vez de executarANALYZE
em todos os esquemas / tabelas e esperar eternamente por uma resposta, verifiquei primeiro os resultados usando a 'terceira abordagem' e essa (usandopg_class
) retornou contagens muito precisas.Aqui está uma solução que não requer funções para obter uma contagem precisa para cada tabela:
query_to_xml
executará a consulta SQL passada e retornará um XML com o resultado (a contagem de linhas para essa tabela). O externoxpath()
extrairá as informações de contagem desse xml e as converterá em um númeroA tabela derivada não é realmente necessária, mas facilita
xpath()
um pouco a compreensão - caso contrário, o todoquery_to_xml()
precisaria ser passado para axpath()
função.fonte
query_to_jsonb()
.select count(*)
em todas as tabelas.xpath()
função só é aplicado a uma única fileira - o resultado de acount(*)
Para obter estimativas, consulte a resposta de Greg Smith .
Para obter contagens exatas, as outras respostas até agora são atormentadas por alguns problemas, alguns deles sérios (veja abaixo). Aqui está uma versão que é esperançosamente melhor:
Leva um nome de esquema como parâmetro ou
public
se nenhum parâmetro for fornecido.Para trabalhar com uma lista específica de esquemas ou uma lista proveniente de uma consulta sem modificar a função, ela pode ser chamada de dentro de uma consulta como esta:
Isso produz uma saída de 3 colunas com o esquema, a tabela e a contagem de linhas.
Agora, aqui estão alguns problemas nas outras respostas que essa função evita:
Os nomes de tabelas e esquemas não devem ser injetados no SQL executável sem serem citados, com
quote_ident
ou com aformat()
função mais moderna com sua%I
sequência de formato. Caso contrário, uma pessoa mal-intencionada pode nomear sua tabela,tablename;DROP TABLE other_table
que é perfeitamente válida como um nome de tabela.Mesmo sem os problemas de injeção de SQL e caracteres engraçados, o nome da tabela pode existir em variantes diferentes por caso. Se uma tabela for nomeada
ABCD
e outraabcd
, elaSELECT count(*) FROM...
deverá usar um nome entre aspas, caso contrário, ela será ignoradaABCD
e contadaabcd
duas vezes. O%I
formato de faz isso automaticamente.information_schema.tables
lista tipos compostos personalizados, além de tabelas, mesmo quando table_type for'BASE TABLE'
(!). Como conseqüência, não podemos interagirinformation_schema.tables
, caso contrário, corremos o risco de terselect count(*) from name_of_composite_type
e isso falharia. OTOHpg_class where relkind='r'
deve sempre funcionar bem.O tipo de COUNT () é
bigint
nãoint
. Podem existir tabelas com mais de 2,15 bilhões de linhas (executar uma contagem (*) nelas é uma má idéia).Um tipo permanente não precisa ser criado para que uma função retorne um conjunto de resultados com várias colunas.
RETURNS TABLE(definition...)
é uma alternativa melhor.fonte
Se você não se importar com dados potencialmente obsoletos, poderá acessar as mesmas estatísticas usadas pelo otimizador de consultas .
Algo como:
fonte
ANALYZE
sobre a mesa, as estatísticas poderão sair muito ruins. É uma questão de carga do banco de dados e como o banco de dados é configurado (se as estatísticas forem atualizadas com mais frequência, as estatísticas serão mais precisas, mas poderão reduzir o desempenho do tempo de execução). Por fim, a única maneira de obter dados precisos é executarselect count(*) from table
em todas as tabelas.A resposta prática e hacky para as pessoas que tentam avaliar qual plano Heroku elas precisam e mal podem esperar para o contador de linhas lentas da heroku se atualizar:
Basicamente você deseja executar
\dt
empsql
, copiar os resultados para o seu editor de texto favorito (ele será parecido com este:), execute uma pesquisa regex e substitua assim:
para:
o que produzirá algo muito parecido com isso:
(Você precisará remover o último
union
e adicionar o ponto e vírgula no final manualmente)Execute-o
psql
e pronto.fonte
select '$1', count(*) from $1 union/g
/g
(manterunion
) e adicionar um ponto-e-vírgula (;
) no final. Não se esqueça de remover o últimounion
antes do ponto e vírgula.union
antes do ponto e vírgula" é o que eu quis dizer :) Adicionado a palavra "passado" para esclarecerNão tenho certeza se uma resposta no bash é aceitável para você, mas FWIW ...
fonte
select count(*) from table_name;
no OP!Normalmente, não confio em estatísticas, especialmente no PostgreSQL.
fonte
dsql2('select count(*) from livescreen.'||table_name)
ou melhor, podendo ser transformada em uma função própria.Não lembro o URL de onde o coletei. Mas espero que isso ajude você:
A execução
select count_em_all();
deve levar a contagem de linhas de todas as suas tabelas.fonte
quote_ident(t_name.relname)
) para garantir suporte adequado a nomes incomuns ("nome da coluna", por exemplo).SELECT * FROM count_em_all() as r ORDER BY r.num_rows DESC;
Dois passos simples:
(Nota: não é necessário alterar nada - basta copiar e colar)
1. criar função
2. Execute esta consulta para obter a contagem de linhas para todas as tabelas
ou
Para obter linhas, conta em tabela
fonte
Fiz uma pequena variação para incluir todas as tabelas, também para tabelas não públicas.
use
select count_em_all();
para chamá-lo.Espero que você ache isso útil. Paulo
fonte
Isso funcionou para mim
fonte
Eu gosto da resposta de Daniel Vérité . Mas quando você não pode usar uma instrução CREATE, pode usar uma solução bash ou, se você é um usuário do Windows, uma solução PowerShell:
fonte
Eu queria o total de todas as tabelas + uma lista de tabelas com suas contagens. Um pouco como um gráfico de desempenho de onde mais tempo foi gasto
Obviamente, você também pode colocar uma
LIMIT
cláusula nos resultados desta versão para obter os maioresn
infratores e também o total.Uma coisa que deve ser notada sobre isso é que você precisa deixá-lo descansar um pouco após a importação em massa. Testei isso adicionando 5000 linhas a um banco de dados em várias tabelas usando dados de importação reais. Mostrou 1800 registros por aproximadamente um minuto (provavelmente uma janela configurável)
Isso é baseado no https://stackoverflow.com/a/2611745/1548557 trabalho, portanto, obrigado e reconhecimento pela consulta a ser usada no CTE
fonte