usar tables postgres funcion all postgresql count database-table

postgresql - tables - sql count distinct postgres



¿Cómo encuentra el recuento de filas para todas sus tablas en Postgres? (11)

Aquí hay una solución que no requiere funciones para obtener un conteo preciso para cada tabla:

select table_schema, table_name, (xpath(''/row/cnt/text()'', xml_count))[1]::text::int as row_count from ( select table_name, table_schema, query_to_xml(format(''select count(*) as cnt from %I.%I'', table_schema, table_name), false, true, '''') as xml_count from information_schema.tables where table_schema = ''public'' --<< change here for the schema you want ) t

query_to_xml ejecutará la consulta SQL pasada y devolverá un XML con el resultado (el recuento de filas para esa tabla). El xpath() externo xpath() luego extraerá la información de conteo de ese xml y la convertirá en un número

La tabla derivada no es realmente necesaria, pero hace que la xpath() un poco más fácil de entender; de lo contrario, toda la consulta a query_to_xml() debería pasar a la función xpath() .

Estoy buscando una manera de encontrar el recuento de filas para todas mis tablas en Postgres. Sé que puedo hacer esto de una mesa a la vez con:

SELECT count(*) FROM table_name;

pero me gustaría ver el recuento de filas para todas las mesas y luego ordenar por eso para tener una idea de cuán grandes son todas mis mesas.


Dos pasos simples:
(Nota: No es necesario cambiar nada, solo copiar y pegar)
1. crear función

create function cnt_rows(schema text, tablename text) returns integer as $body$ declare result integer; query varchar; begin query := ''SELECT count(1) FROM '' || schema || ''.'' || tablename; execute query into result; return result; end; $body$ language plpgsql;

2. Ejecute esta consulta para obtener el recuento de filas para todas las tablas

select sum(cnt_rows) as total_no_of_rows from (select cnt_rows(table_schema, table_name) from information_schema.tables where table_schema not in (''pg_catalog'', ''information_schema'') and table_type=''BASE TABLE'') as subq;

o
Para obtener filas cuenta en tabla

select table_schema, table_name, cnt_rows(table_schema, table_name) from information_schema.tables where table_schema not in (''pg_catalog'', ''information_schema'') and table_type=''BASE TABLE'' order by 3 desc


Hay tres formas de obtener este tipo de conteo, cada uno con sus propias compensaciones.

Si desea un conteo verdadero, debe ejecutar la instrucción SELECT como la que usó contra cada tabla. Esto se debe a que PostgreSQL mantiene la información de visibilidad de la fila en la misma fila, no en ningún otro lugar, por lo que cualquier conteo exacto solo puede ser relativo a alguna transacción. Obtiene un recuento de lo que ve la transacción en el momento en que se ejecuta. Puede automatizar esto para que se ejecute en cada tabla de la base de datos, pero probablemente no necesite ese nivel de precisión o desee esperar tanto tiempo.

El segundo enfoque señala que el recopilador de estadísticas realiza un seguimiento de aproximadamente cuántas filas están "activas" (no se eliminan ni quedan obsoletas por actualizaciones posteriores) en ningún momento. Este valor puede estar desactivado un poco en una actividad pesada, pero generalmente es una buena estimación:

SELECT schemaname,relname,n_live_tup FROM pg_stat_user_tables ORDER BY n_live_tup DESC;

Eso también puede mostrarle cuántas filas están muertas, lo que en sí mismo es un número interesante para monitorear.

La tercera forma es tener en cuenta que el comando ANALIZAR del sistema, que se ejecuta mediante el proceso autovacuum regularmente a partir de PostgreSQL 8.3 para actualizar las estadísticas de la tabla, también calcula una estimación de fila. Puedes agarrar eso de esta manera:

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;

Es difícil decir cuál de estas consultas es mejor usar. Normalmente tomo esa decisión en función de si hay más información útil que también quiero usar dentro de pg_class o dentro de pg_stat_user_tables. Para propósitos básicos de conteo, solo para ver qué tan grandes son las cosas en general, cualquiera debería ser lo suficientemente preciso.


Hice una pequeña variación para incluir todas las tablas, también para tablas no públicas.

CREATE TYPE table_count AS (table_schema TEXT,table_name TEXT, num_rows INTEGER); CREATE OR REPLACE FUNCTION count_em_all () RETURNS SETOF table_count AS '' DECLARE the_count RECORD; t_name RECORD; r table_count%ROWTYPE; BEGIN FOR t_name IN SELECT table_schema,table_name FROM information_schema.tables where table_schema !=''''pg_catalog'''' and table_schema !=''''information_schema'''' ORDER BY 1,2 LOOP FOR the_count IN EXECUTE ''''SELECT COUNT(*) AS "count" FROM '''' || t_name.table_schema||''''.''''||t_name.table_name LOOP END LOOP; r.table_schema := t_name.table_schema; r.table_name := t_name.table_name; r.num_rows := the_count.count; RETURN NEXT r; END LOOP; RETURN; END; '' LANGUAGE plpgsql;

use select count_em_all(); llamarlo

Espero que encuentres esto útil. Pablo


La respuesta intrépida y práctica para las personas que intentan evaluar qué plan Heroku necesitan y no pueden esperar a que se actualice el contador de filas lentas de heroku:

Básicamente, desea ejecutar /dt en psql , copie los resultados a su editor de texto favorito (se verá así:

public | auth_group | table | axrsosvelhutvw public | auth_group_permissions | table | axrsosvelhutvw public | auth_permission | table | axrsosvelhutvw public | auth_user | table | axrsosvelhutvw public | auth_user_groups | table | axrsosvelhutvw public | auth_user_user_permissions | table | axrsosvelhutvw public | background_task | table | axrsosvelhutvw public | django_admin_log | table | axrsosvelhutvw public | django_content_type | table | axrsosvelhutvw public | django_migrations | table | axrsosvelhutvw public | django_session | table | axrsosvelhutvw public | exercises_assignment | table | axrsosvelhutvw

), luego ejecuta una búsqueda de expresiones regulares y reemplaza así:

^[^|]*/|/s+([^|]*?)/s+/| table /|.*$

a:

select ''/1'', count(*) from /1 union/g

Lo que te dará algo muy parecido a esto:

select ''auth_group'', count(*) from auth_group union select ''auth_group_permissions'', count(*) from auth_group_permissions union select ''auth_permission'', count(*) from auth_permission union select ''auth_user'', count(*) from auth_user union select ''auth_user_groups'', count(*) from auth_user_groups union select ''auth_user_user_permissions'', count(*) from auth_user_user_permissions union select ''background_task'', count(*) from background_task union select ''django_admin_log'', count(*) from django_admin_log union select ''django_content_type'', count(*) from django_content_type union select ''django_migrations'', count(*) from django_migrations union select ''django_session'', count(*) from django_session ;

(Deberás eliminar la union y agregar el punto y coma al final manualmente)

Ejecutarlo en psql y listo.

?column? | count --------------------------------+------- auth_group_permissions | 0 auth_user_user_permissions | 0 django_session | 1306 django_content_type | 17 auth_user_groups | 162 django_admin_log | 9106 django_migrations | 19 [..]


Me gusta la answer Daniel Vérité. Pero cuando no puede usar una sentencia CREATE, puede usar una solución de bash o, si es un usuario de Windows, una de PowerShell:

# You don''t need this if you have pgpass.conf $env:PGPASSWORD = "userpass" # Get table list $tables = & ''C:/Program Files/PostgreSQL/9.4/bin/psql.exe'' -U user -w -d dbname -At -c "select table_name from information_schema.tables where table_type=''BASE TABLE'' AND table_schema=''schema1''" foreach ($table in $tables) { & ''C:/path_to_postresql/bin/psql.exe'' -U root -w -d dbname -At -c "select ''$table'', count(*) from $table" }


No estoy seguro si una respuesta en bash es aceptable para usted, pero FWIW ...

PGCOMMAND=" psql -h localhost -U fred -d mydb -At -c /" SELECT table_name FROM information_schema.tables WHERE table_type=''BASE TABLE'' AND table_schema=''public'' /"" TABLENAMES=$(export PGPASSWORD=test; eval "$PGCOMMAND") for TABLENAME in $TABLENAMES; do PGCOMMAND=" psql -h localhost -U fred -d mydb -At -c /" SELECT ''$TABLENAME'', count(*) FROM $TABLENAME /"" eval "$PGCOMMAND" done


No recuerdo la URL de donde recogí esto. Pero espero que esto te ayude:

CREATE TYPE table_count AS (table_name TEXT, num_rows INTEGER); CREATE OR REPLACE FUNCTION count_em_all () RETURNS SETOF table_count AS '' DECLARE the_count RECORD; t_name RECORD; r table_count%ROWTYPE; BEGIN FOR t_name IN SELECT c.relname FROM pg_catalog.pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind = ''''r'''' AND n.nspname = ''''public'''' ORDER BY 1 LOOP FOR the_count IN EXECUTE ''''SELECT COUNT(*) AS "count" FROM '''' || t_name.relname LOOP END LOOP; r.table_name := t_name.relname; r.num_rows := the_count.count; RETURN NEXT r; END LOOP; RETURN; END; '' LANGUAGE plpgsql;

Ejecutando select count_em_all(); Debería obtener el número de filas de todas sus tablas.


Normalmente no confío en las estadísticas, especialmente en PostgreSQL.

SELECT table_name, dsql2(''select count(*) from ''||table_name) as rownum FROM information_schema.tables WHERE table_type=''BASE TABLE'' AND table_schema=''livescreen'' ORDER BY 2 DESC;

CREATE OR REPLACE FUNCTION dsql2(i_text text) RETURNS int AS $BODY$ Declare v_val int; BEGIN execute i_text into v_val; return v_val; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100;


Para obtener estimaciones, vea la respuesta de Greg Smith .

Para obtener recuentos exactos, las otras respuestas hasta ahora están plagadas de algunos problemas, algunos de ellos serios (ver más abajo). Aquí hay una versión que espero sea mejor:

CREATE FUNCTION rowcount_all(schema_name text default ''public'') RETURNS table(table_name text, cnt bigint) as $$ declare table_name text; begin for table_name in SELECT c.relname FROM pg_class c JOIN pg_namespace s ON (c.relnamespace=s.oid) WHERE c.relkind = ''r'' AND s.nspname=schema_name LOOP RETURN QUERY EXECUTE format(''select cast(%L as text),count(*) from %I.%I'', table_name, schema_name, table_name); END LOOP; end $$ language plpgsql;

Toma un nombre de esquema como parámetro, o public si no se da ningún parámetro.

Para trabajar con una lista específica de esquemas o una lista proveniente de una consulta sin modificar la función, se puede llamar desde una consulta como esta:

WITH rc(schema_name,tbl) AS ( select s.n,rowcount_all(s.n) from (values (''schema1''),(''schema2'')) as s(n) ) SELECT schema_name,(tbl).* FROM rc;

Esto produce una salida de 3 columnas con el esquema, la tabla y el conteo de filas.

Ahora aquí hay algunos problemas en las otras respuestas que esta función evita:

  • Los nombres de tablas y esquemas no se deben inyectar en el SQL ejecutable sin quote_ident , ya sea con quote_ident o con la función format() más moderna con su cadena de formato %I De lo contrario, alguna persona maliciosa puede nombrar su tabla nombre de tabla tablename;DROP TABLE other_table que es perfectamente válido como nombre de tabla.

  • Incluso sin la inyección de SQL y los problemas de caracteres divertidos, el nombre de la tabla puede existir en variantes diferentes según el caso. Si una tabla se llama ABCD y otra abcd , el SELECT count(*) FROM... debe usar un nombre entre comillas, de lo contrario salteará ABCD y contará abcd dos veces. El %I de formato lo hace automáticamente.

  • information_schema.tables enumera tipos compuestos personalizados además de tablas, incluso cuando table_type es ''BASE TABLE'' (!). Como consecuencia, no podemos iterar en information_schema.tables , de lo contrario, nos arriesgamos a tener un select count(*) from name_of_composite_type y eso fallaría. OTOH pg_class where relkind=''r'' siempre debería funcionar bien.

  • El tipo de COUNT () es bigint , no int . Sin embargo, es posible que existan tablas con más de 2,150 millones de filas (sin embargo, ejecutar una cuenta (*) en ellas).

  • No es necesario crear un tipo permanente para que una función devuelva un conjunto de resultados con varias columnas. RETURNS TABLE(definition...) es una mejor alternativa.