What does each column in an archive's table of contents mean? (pg_dump/pg_restore) - postgresql

I'm using pg_restore to reconstitute a database I've backed up. As suggested in the pg_restore docs (https://www.postgresql.org/docs/curren/app-pgrestore.html), I've created a .list file with the archive's table of contents.
Nothing is wrong per se, but I'm struggling to figure out what every column in this ToC means. They each look like this:
5602; 0 16476 TABLE DATA public <table_name> postgres
The first column is the archive id for that table, but what do the next two numbers mean? In my ToC the first non-archive column is always zero but in other examples that's not true.

The fields pertain to:
Archive ID
Catalog Table OID (0 in your case, because that row pertains to TABLE DATA and not a table. A proc would get the value of SELECT oid FROM pg_class were relname = 'pg_proc' here, a table would get SELECT oid FROM pg_class where relname = 'pg_class', etc.)
Table OID (16476 is the oid you would find in pg_class)
Description (TABLE DATA in your example)
Schema (public in your example)
Name (<table_name>)
Owner (postgres in your example)

Related

Difference between oid and relfilenode

I am reading Internals of postgreSQL chp 1 and I am unable to understand the difference between object identifier and relfilenode.
Tables and indexes as database objects are internally managed by individual OIDs, while those data files are managed by the variable, relfilenode. The relfilenode values of tables and indexes basically but not always match the respective OIDs
I get that both these are the attributes of the system catalog 'pg_class' and OID can be thought of as the primary key of the table, so what is the purpose of relfilenode and how is it different from OID?
relfilenode is the prefix for the name of the files that make up the table. Initially it is identical to the immutable object ID (oid), but SQL statements that rewrite the table will modify it (for example VACUUM (FULL), CLUSTER, TRUNCATE or the variants of ALTER TABLE that rewrite the table).

pg_largeobject huge, but no tables have OID column type

postrgresql noob, PG 9.4.x, no access to application code, developers, anyone knowledgeable about it
User database CT has 427GB pg_largeobject (PGLOB) table, next largest table is 500ish MB.
Per this post (Does Postgresql use PGLOB internally?) a very reputable member said postgresql does not use PGLOB internally.
I have reviewed the schema of all user tables in the database, and none of them are of type OID (or lo) - which is the value used for PGLOB rows to tie the collection of blob chunks back to a referencing table row. I think this means I cannot use vacuumlo (vacuumlo) to delete orphaned PGLOB rows because that utility searches user objects for those two data types in user tables.
I HAVE identified a table with an integer field type that has int values that match LOID values in PGLOB. This seems to indicate that the developers somehow got their blobs into PGLOB using the integer value stored in a user table row.
QUESTION: Is that last statement possible?
A) If it is not, what could be adding all this data to PGLOB table?
B) If it is possible, is there a way I can programatically search ALL tables for integer values that might represent rows in PGLOB?
NEED: I DESPERATELY need to reduce the size of the PGLOB table, as we are running out of disk space. And no, we cannot add space to existing disk per admin. So I somehow need to determine if there are LOID values in PGLOB that do NOT exist in ANY user tables as integer-type fields and then run lo_unlink to remove the rows. This could get me more usable 8K pages in the table.
BTW, I have also run pg_freespace on PGLOB, and it identified that most of the pages in PGLOB did not contain enough space in which to insert another blob chunk.
THANKS FOR THE ASSISTANCE!
Not really an answer but thinking out loud:
As you found all large objects are stored in a single table. The oid field you refer to is something you add to a table so you can have a pointer to a particular LO oid in pg_largeobject. That being said there is nothing compelling you to store that info in a table, you can just create LO's in pg_largeobject. From the looks of it, and just a guess, the developers stored the oid's as integer's with the intent of doing integer::oid to get a particular LO back as needed. I would look at other information is stored in that table to see if helps determine what the LO's are for?
Also you might join the integer::oid values to the oid(loid) in pg_catalog to see if that table accounts for all of them?
I was able to do a detailed analysis of all user tables in the database, find all columns that contained numeric data with no decimals, and then do a a query from pg_largeobject with a NOT EXISTS clause for every table matching pglob.loid against the appropriate field(s) in the user tables.
I found 25794 LOIDs that could be DELETEd from the PGLOB table, totaling 3.4M rows.
select distinct loid
into OrphanedBLOBs
from pg_largeobject l
where NOT exists (select * from tbl1 cn where cn.noteid = l.loid)
and not exists (select * from tbl1 d where d.document = l.loid)
and not exists (select * from tbl1 d where d.reportid = l.loid)
I used that table to execute lo_unlink(loid) for each of the LOIDs.

How to get the describe tables from the Redshift and ALTER it

I have create a redshift cluster and created a db inside.
My schema is new_schema
I have created 2 tables inside two tables inside table1, table2
My Question.
I want to list the datatypes of table1
I need to change the datatype of description which is inside the table1 which is of VARCHAR to TEXT
I have tried to list the datatypes of table1 with below query but nothing listing
SELECT * FROM PG_TABLE_DEF WHERE schemaname = 'new_schema';
A few possibilities as to why you are not seeing the expected results. Most likely is that new_schema isn't in your search_path. Pg_table_info only return info for tables in your search_path - see: https://docs.aws.amazon.com/redshift/latest/dg/r_PG_TABLE_DEF.html
Another possibility is that the tables have no data rows (no blocks assigned) and this can lead to incomplete info from some system tables.
Another possibility is that the tables were not committed by the creating session and being checked by a different session. Since you say that you are creating a new db this comes to mind.
Are the tables visible in svv_table_info?
Also the premise of changing varchar to text is a bit off. From https://docs.aws.amazon.com/redshift/latest/dg/r_Character_types.html#r_Character_types-text-and-bpchar-types
You can create an Amazon Redshift table with a TEXT column, but it is
converted to a VARCHAR(256) column that accepts variable-length values
with a maximum of 256 characters.
So it seems like the objective you are trying to achieve is a bit off.

create (or copy) table schema using postgres_fdw or dblink

I have many tables in different databases and want to bring them to a database.
It seems like I have to create foreign table in the database (where I want to merge them all) with schemas of all the tables.
I am sure, there is a way to automate this (by the way, I am going to use psql command) but I do not know where to start.
what I have found so far is I can use
select * from information_schema.columns
where table_schema = 'public' and table_name = 'mytable'
I added more detail explanation.
I wanted to copy tables from another database
the tables have same column names and data type
using postgres_fdw, I needed to set up a field name and data type for each tables (the table names are also same)
then, I want to union the tables have same name all to have one single table.
for that, I am going to add prefix on table
for instance, mytable in db1, mytable in db2, mytable in db3 as in
db1_mytable, db2_mytable, db3_mytable in my local database.
Thanks to Albe's comment, I managed it and now I need to figure out doing 4th step using psql command.

Create empty table in postgresql

i want to create a simple table inside a database in postgresql.
From the Documentation i have CREATE TABLE will create a new, initially empty table in the current database. The table will be owned by the user issuing the command.
With this command
CREATE TABLE *table_name*;
I thought i get a new empty table.But psql throws ERROR: syntax error at or near ";". When i user an empty argument list like:
CREATE TABLE *table_name*();
psql tells me that the table was created through
postgres=# create table *table_name*();
CREATE TABLE
But \l shows is not showing the newly created table. And its also not possible to login with psql -d table_name -U user_name. Can anyone help?
You can have a table with no columns, and even with some rows in it:
CREATE TABLE nocolumn (dummy INTEGER NOT NULL PRIMARY KEY)
;
INSERT INTO nocolumn(dummy) VALUES (1);
ALTER TABLE nocolumn
DROP COLUMN dummy;
\d nocolumn
SELECT COUNT(*) FROM nocolumn;
Output:
CREATE TABLE
INSERT 0 1
ALTER TABLE
Table "tmp.nocolumn"
Column | Type | Modifiers
--------+------+-----------
count
-------
1
(1 row)
You seem to be confusing the terms database and table
But \l is not showing the newly created table.
Of course \l will not show you that table, because \l will list databases not relations. To see all tables you need to use \d or \dt.
And its also not possible to login with psql -d table_name -U user_name
Of course this is not possible, because the -d parameter is used to specify a database, not a table
I'm not sure why other answers suggest to create a table with a column and then ignore that column. It is certainly possible, but it seems different from what you tried to do.
It seems you have to use parenthesis:
postgres=# CREATE TABLE t ();
CREATE TABLE
To insert a row:
postgres=# INSERT INTO t DEFAULT VALUES;
INSERT 0 1
To count the rows you inserted:
postgres=# SELECT FROM t;
--
(2 rows)
You can't delete a single rows, because all rows are equal. But to completely empty the table, you can use DELETE without WHERE, or TRUNCATE TABLE.
You can find more info here: PostgreSQL: Tables without columns.
That said, I have to say that I understand "empty table" as "table without rows", not necessarily without columns.
An hour ago i suggested to add at least one column like this:
create table tab1 (columnname varchar(42) not null)
But this seems to be not necessary as a commentator just told. (I consider to keep the wrong answer here instead of deleting it, to prevent that others suggest the same)