Get PostgreSQL statistics for all tables? - postgresql

I have seen that PostgreSQL have several statistics depending on every table's OID (like the number of inserts, and so) 1.
What I am looking for is some kind of SELECT query or something that would sum up everything for every table.
It would be something like:
SELECT SUM(pg_stat_get_db_tuples_returned(SELECT oid FROM pg_class));
Or something like that. I would apreciate any help in here.

Do you mean this:
SELECT SUM(pg_stat_get_db_tuples_returned(oid))
from pg_class;

Something like this, with your choice of stats function, aggregates the stats function on all tables except temporary and system catalog tables:
SELECT
sum(pg_stat_get_db_tuples_returned(c.oid))
FROM pg_catalog.pg_class c
INNER JOIN pg_namespace n ON (c.relnamespace = n.oid)
WHERE NOT (n.nspname LIKE ANY(ARRAY['pg_temp%','pg_catalog','information_schema']));
Note that pg_toast schemas are included in this, as I presume you want your stats to include any TOAST side-tables. If you don't, add pg_toast% to the exclusions.
Edit: I was using the construct:
(quote_ident(n.nspname)||'.'||quote_ident(c.relname))::regclass
to get the table oid, but that's just silly when it's right there in pg_class; it's ridiculously roundabout as shown by a_horse_with_no_name.

Related

PostgreSQL change data type default query

While I am doing monitoring with my PostgreSql server, I found out that this query frequently shown up.
select t.oid, t.typname from pg_type t where t.typtype='b'
and because I have a lot of table, that query will take long time to process.
Is it possible for me to custom that query into another query like
select t.oid, t.typname
from pg_type t
left join pg_type base_type on t.typelem=base_type.oid
where t.typtype='b'
and (base_type.oid is null or base_type.typtype='b')
or maybe another suggestion will be good
thank you
Try to find out what issues this query, then you can fix the problem. It may well be some ORM, framework or other tool.
Having extremely many tables, users, schemas or other objects is a bad idea, because the catalogs are not built and indexed for that.

PostgreSQL nested selects

Is there anybody who can help me with making a query with the following functionality:
Let's have a simple statement like:
SELECT relname FROM pg_catalog.pg_class WHERE relkind = 'r';
This will produce a nice result with a single column - the names of all tables.
Now lets imagine that one of the tables has name "table1". If we execute:
SELECT count(*) FROM table1;
we will get the number of rows of the table "table1".
Now the real question - how these two queries can be unified and to have one query, which to give the result of two columns: name of the table and number of rows? Written in pseudo SQL it should be something like this:
SELECT relname, (SELECT count(*) FROM relname::[as table name]) FROM pg_catalog.pg_class WHERE relkind = 'r';
And here is and example - if there are 3 tables in the database and the names are table1, table2 and table 3, and they have respectively 20, 30 and 40 rows, the query result should be like this:
-------------
|relname| rows|
|-------------|
|table1 | 20|
|-------------|
|table2 | 30|
|-------------|
|table3 | 40|
-------------
Thanks to everyone who is willing to help ;-)
P.S. Yes I know that the table name is not schema-qualified ;-) Let's hope that all tables in the database have unique names ;-)
(Corrected typos from rename to relname in last query)
EDIT1: The question is not related to "how can I find the number of rows in a table". What I'm asking is: how to build a query with 2 selects and the second to have as FROM the value of a column from the result of the first select.
EDIT2: As #jdigital suggested I've tried the dynamic querying and it does the job, but can be used only in PL/pgSQL. So it doesn't fit my needs. In additional I tried with PREPARE and EXECUTE statement - yet again it is not working. Anyway - I'll stick with the two queries approach. But I'm damn sure that PostgreSQL is capable of this ....
With PL/pgSQL (postgres SQL Procedural Language), you can execute dynamic queries by building a string and then executing it as SQL. Note that this is postgres-specific, but other databases are likely to have something equivalent. Even more generally, if you are willing to go beyond SQL, you can do this with any programming language (or shell/cmd script).
By the way, you'll get better results searching for "postgres dynamic query" since "nested select" has a different meaning.

Postgres subquery has access to column in a higher level table. Is this a bug? or a feature I don't understand?

I don't understand why the following doesn't fail. How does the subquery have access to a column from a different table at the higher level?
drop table if exists temp_a;
create temp table temp_a as
(
select 1 as col_a
);
drop table if exists temp_b;
create temp table temp_b as
(
select 2 as col_b
);
select col_a from temp_a where col_a in (select col_a from temp_b);
/*why doesn't this fail?*/
The following fail, as I would expect them to.
select col_a from temp_b;
/*ERROR: column "col_a" does not exist*/
select * from temp_a cross join (select col_a from temp_b) as sq;
/*ERROR: column "col_a" does not exist
*HINT: There is a column named "col_a" in table "temp_a", but it cannot be referenced from this part of the query.*/
I know about the LATERAL keyword (link, link) but I'm not using LATERAL here. Also, this query succeeds even in pre-9.3 versions of Postgres (when the LATERAL keyword was introduced.)
Here's a sqlfiddle: http://sqlfiddle.com/#!10/09f62/5/0
Thank you for any insights.
Although this feature might be confusing, without it, several types of queries would be more difficult, slower, or impossible to write in sql. This feature is called a "correlated subquery" and the correlation can serve a similar function as a join.
For example: Consider this statement
select first_name, last_name from users u
where exists (select * from orders o where o.user_id=u.user_id)
Now this query will get the names of all the users who have ever placed an order. Now, I know, you can get that info using a join to the orders table, but you'd also have to use a "distinct", which would internally require a sort and would likely perform a tad worse than this query. You could also produce a similar query with a group by.
Here's a better example that's pretty practical, and not just for performance reasons. Suppose you want to delete all users who have no orders and no tickets.
delete from users u where
not exists (select * from orders o where o.user_d = u.user_id)
and not exists (select * from tickets t where t.user_id=u.ticket_id)
One very important thing to note is that you should fully qualify or alias your table names when doing this or you might wind up with a typo that completely messes up the query and silently "just works" while returning bad data.
The following is an example of what NOT to do.
select * from users
where exists (select * from product where last_updated_by=user_id)
This looks just fine until you look at the tables and realize that the table "product" has no "last_updated_by" field and the user table does, which returns the wrong data. Add the alias and the query will fail because no "last_updated_by" column exists in product.
I hope this has given you some examples that show you how to use this feature. I use them all the time in update and delete statements (as well as in selects-- but I find an absolute need for them in updates and deletes often)

Getting a list of tables that a view/table depends on in PostgreSQL

In PostgreSQL, is there a way to get all of the tables that a view/table depends on based on its use of foreign keys and access to a given table?
Basically, I want to be able to copy the structure of a view/table using a script and want to be able to automatically get the list of tables that I would also need to copy in order for everything to still work right.
This response appears to be headed in the right direction, but doesn't give me the results that I expect/need. Any suggestions?
Using the info from Andy Lester, I was able to come up with the following queries to retrieve the information that I needed.
Get Tables that Foreign Keys refer to:
SELECT cl2.relname AS ref_table
FROM pg_constraint as co
JOIN pg_class AS cl1 ON co.conrelid=cl1.oid
JOIN pg_class AS cl2 ON co.confrelid=cl2.oid
WHERE co.contype='f' AND cl1.relname='TABLENAME'
ORDER BY cl2.relname;
Get Tables that a View or Rules from a Table refer to:
SELECT cl_d.relname AS ref_table
FROM pg_rewrite AS r
JOIN pg_class AS cl_r ON r.ev_class=cl_r.oid
JOIN pg_depend AS d ON r.oid=d.objid
JOIN pg_class AS cl_d ON d.refobjid=cl_d.oid
WHERE cl_d.relkind IN ('r','v') AND cl_r.relname='TABLENAME'
GROUP BY cl_d.relname
ORDER BY cl_d.relname;
Assuming you have your foreign keys set up correctly, use pg_dump to dump the table definitions.
pg_dump -s -t TABLENAME
I think it is a quite bad idea. Just copy the whole database, I think that the application wants to have all data, not only data from one table.
What's more, there are also triggers, that could depend on some tables, but to know that you'd have to make not so easy code analysis.
In psql, adding + to the usual \d gives you a "Referenced by" list along with the table definition.
\d+ tablename

interrogating table lock schemes in T-SQL

Is there some means of querying the system tables to establish which tables are using what locking schemes? I took a look at the columns in sysobjects but nothing jumped out.
aargh, just being an idiot:
SELECT name, lockscheme(name)
FROM sysobjects
WHERE type="U"
ORDER BY name
take a look at the syslockinfo and syslocks system tables
you can also run the sp_lock proc