Checking fillfactor setting for tables and indexes - postgresql

There is maybe some function to check the fillfactor for indexes and tables? I've tried already \d+ but have basic definition only, without fillfactor value:
Index "public.tab1_pkey"
Column | Type | Definition | Storage
--------+--------+------------+---------
id | bigint | id | plain
primary key, btree, for table "public.tab1"
For tables haven't found anything. If table was created with fillfactor other than default:
CREATE TABLE distributors (
did integer,
name varchar(40),
UNIQUE(name) WITH (fillfactor=70)
)
WITH (fillfactor=70);
Then \d+ distributorsshows non-standard fillfactor.
Table "public.distributors"
Column | Type | Modifiers | Storage | Stats target | Description
--------+-----------------------+-----------+----------+--------------+-------------
did | integer | | plain | |
name | character varying(40) | | extended | |
Indexes:
"distributors_name_key" UNIQUE CONSTRAINT, btree (name) WITH (fillfactor=70)
Has OIDs: no
Options: fillfactor=70
But maybe there is a way to get this value without parsing output?

You need to query the pg_class system table:
select t.relname as table_name,
t.reloptions
from pg_class t
join pg_namespace n on n.oid = t.relnamespace
where t.relname in ('tab11_pkey', 'tab1')
and n.nspname = 'public'
reloptions is an array, with each element containing one option=value definition. But it will be null for relations that have the default options.

Related

Optimizing Postgres Count For Aggregated Select

I have a query that is intended to retrieve the counts of each grouped product like so
SELECT
product_name,
product_color,
(array_agg("product_distributor"))[1] AS "product_distributor",
(array_agg("product_release"))[1] AS "product_release",
COUNT(*) AS "count"
FROM
product
WHERE
product.id IN (
SELECT
id
FROM
product
WHERE
(product_name ilike "%red%"
OR product_color ilike "%red%")
AND product_type = 1)
GROUP BY
product_name, product_color
LIMIT
1000
OFFSET
0
This query is run on the following table
Column | Type | Collation | Nullable | Default
---------------------+--------------------------+-----------+----------+---------
product_type | integer | | not null |
id | integer | | not null |
product_name | citext | | not null |
product_color | character varying(255) | | |
product_distributor | integer | | |
product_release | timestamp with time zone | | |
created_at | timestamp with time zone | | not null |
updated_at | timestamp with time zone | | not null |
Indexes:
"product_pkey" PRIMARY KEY, btree (id)
"product_distributer_index" btree (product_distributor)
"product_product_type_name_color" UNIQUE, btree (product_type, name, color)
"product_product_type_index" btree (product_type)
"product_name_color_index" btree (name, color)
Foreign-key constraints:
"product_product_type_fkey" FOREIGN KEY (product_type) REFERENCES product_type(id) ON UPDATE CASCADE ON DELETE CASCADE
"product_product_distributor_id" FOREIGN KEY (product_distributor) REFERENCES product_distributor(id)
How can I improve the performance of this query, specifically the COUNT(*) portion, which when removed improves the query but is requisite?
You may try using an INNER JOIN in place of a WHERE ... IN clause.
WITH selected_products AS (
SELECT id
FROM product
WHERE (product_name ilike "%red%" OR product_color ilike "%red%")
AND product_type = 1
)
SELECT product_name,
product_color,
(ARRAY_AGG("product_distributor"))[1] AS "product_distributor",
(ARRAY_AGG("product_release"))[1] AS "product_release",
COUNT(*) AS "count"
FROM product p
INNER JOIN selected_products sp
ON p.id = sp.id
GROUP BY product_name,
product_color
LIMIT 1000
OFFSET 0
Then create an index on the "product.id" field as follows:
CREATE INDEX product_ids_idx ON product USING HASH (id);

How can I atomically swap table names and its references in postgres without any issues?

I want to swap names of two tables with each other. TableA <> TableB. Also atomically to avoid any issues of read/writes. I know I can do that in a transction.
I am creating the table using - CREATE TABLE TableB (LIKE TableA INCLUDING ALL);. Then I am also copying over the FKs from from A to B. I am then doing a INSERT INTO TABLEA.... to copy over the data as well (irrelevant for this). Once all of this is done, I rename the table using ALTER TABLE RENAME to swap the names TableA <> TableB in a transaction as well. So TableA becomes TableA_Old and TableB becomes the new TableA (example below)
However, this doesn't update the references to this new table in other tables, like TableC which still hold a FK against TableA_Old. When I do a \d+ on the newly renamed table TableA (which was TableB) before, I don't see the references. They still point to TableA_Old.
Here is an example
I create TableA
CREATE TABLE TableA (
id serial PRIMARY KEY
);
testdb=> \d TableA
Table "public.tablea"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+------------------------------------
id | integer | | not null | nextval('tablea_id_seq'::regclass)
Indexes:
"tablea_pkey" PRIMARY KEY, btree (id)
I create TableC with reference to TableA
CREATE TABLE TableC(
id serial PRIMARY KEY,
table_a_id INT,
CONSTRAINT table_a_table_c_fk
FOREIGN KEY(table_a_id)
REFERENCES TableA(id)
);
\d TableC
Table "public.tablec"
Column | Type | Collation | Nullable | Default
------------+---------+-----------+----------+------------------------------------
id | integer | | not null | nextval('tablec_id_seq'::regclass)
table_a_id | integer | | |
Indexes:
"tablec_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"table_a_table_c_fk" FOREIGN KEY (table_a_id) REFERENCES tablea(id)
You can see the reference
Now I create TableB that looks like TableA using a function
create or replace function create_table_like(source_table text, new_table text)
returns void language plpgsql
as $$
declare
rec record;
begin
execute format(
'create table %s (like %s including all)',
new_table, source_table);
for rec in
select oid, conname
from pg_constraint
where contype = 'f'
and conrelid = source_table::regclass
loop
execute format(
'alter table %s add constraint %s %s',
new_table,
replace(rec.conname, source_table, new_table),
pg_get_constraintdef(rec.oid));
end loop;
end $$;
select create_table_like('TableA', 'TableB');
\d TableB
testdb=> select create_table_like('TableA', 'TableB');
create_table_like
-------------------
(1 row)
testdb=> \d TableB
Table "public.tableb"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+------------------------------------
id | integer | | not null | nextval('tablea_id_seq'::regclass)
Indexes:
"tableb_pkey" PRIMARY KEY, btree (id)
Now I rename them
BEGIN;
ALTER TABLE TableA RENAME to TableA_OLD;
ALTER TABLE TableB RENAME to TableA;
COMMIT;
Now when I look at the structures, the reference is still to TableA_OLD from TableC
testdb=> \d TableA
Table "public.tablea"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+------------------------------------
id | integer | | not null | nextval('tablea_id_seq'::regclass)
Indexes:
"tableb_pkey" PRIMARY KEY, btree (id)
testdb=> \d TableB
testdb=> \d TableA_old
Table "public.tablea_old"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+------------------------------------
id | integer | | not null | nextval('tablea_id_seq'::regclass)
Indexes:
"tablea_pkey" PRIMARY KEY, btree (id)
Referenced by:
TABLE "tablec" CONSTRAINT "table_a_table_c_fk" FOREIGN KEY (table_a_id) REFERENCES tablea_old(id)
And TableC is pointing at the old table - REFERENCES tablea_old(id)
testdb=> \d TableC
Table "public.tablec"
Column | Type | Collation | Nullable | Default
------------+---------+-----------+----------+------------------------------------
id | integer | | not null | nextval('tablec_id_seq'::regclass)
table_a_id | integer | | |
Indexes:
"tablec_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"table_a_table_c_fk" FOREIGN KEY (table_a_id) REFERENCES tablea_old(id)
Is there a safe way to do this without dropping and recreating the constraints again?
I know i can also update the relfilenode pointer in pg_class and swap them. However, that is risky since TableB could have a slightly different looking schema. So, I am wondering if I can update some other table in the system catalogue or use a DDL that wouldn't require dropping the constraint.
The true identity of an object is its object ID, a number that is used to refer to the object in foreign key constraints an other internal database matters (with the notable exception of most function bodies). Renaming an object does not change its identity. You have to drop and re-create foreign key constraints.
If you use the rename table command then automatically will be renamed all dependencies objects, foreign keys, references linked to this table. For example:
ALTER TABLE public.table1 RENAME TO table2;

How do we get all columns which are the part of sortkey in Redshift

I need to get all columns, which are the part of sortkey in Redshift.
I tried get information using "select * from svv_table_info" but it have only the information of one column only. Can you let me know, how do I get all columns which are the part of Sortkey for a table.
Thanks,
Sanjeev
Thanks all for your help. I already tried "pg_table_def" table to get sortkey and distkey information but I have seen only pg_catalog and Public schema, I just go through the Amazon developer guide and found we need to add schema to search path using below commands:-
show search_path;
set search_path to '$user', 'public', 'NewSchema';
After adding the "NewSchema" in search path I can see sortkey and distkey information for this schema in pg_table_def
Thanks,
Sanjeev
Sanjeev,
A table called pg_table_def has information about the columns.
In the example below, I created a simple table with four columns and used 2 of these columns as my sort key.
As you can see in my query results the "sort key" field shows a number other than 0 if the column is part of a sort key.
dev=# drop table tb1;
DROP TABLE
dev=# create table tb1 (col1 integer, col2 integer, col3 integer, col4 integer) distkey(col1) sortkey(col2, col4);
CREATE TABLE
dev=# select * from pg_table_def where tablename = 'tb1';
schemaname | tablename | column | type | encoding | distkey | sortkey | notnull
------------+-----------+--------+---------+----------+---------+---------+---------
public | tb1 | col1 | integer | none | t | 0 | f
public | tb1 | col2 | integer | none | f | 1 | f
public | tb1 | col3 | integer | none | f | 0 | f
public | tb1 | col4 | integer | none | f | 2 | f
(4 rows)
What about:
select "column", type, encoding, distkey, sortkey, "notnull"
from pg_table_def
where tablename = 'YOURTABLE'
and sortkey <> 0;

Is trigger or alias returning data in Postgres?

Postgres 9.2.2, Django 1.6.5, Python 2.7.5
Column | Type | Modifiers
---------------+------------------------+------------------------------------
id | integer | not null default nextval('employee_id_seq'::regclass)
first_name | character varying(75) | not null
surname | character varying(75) | not null
mname | character varying(75) |
date_of_birth | date |
staff_id | character varying(20) |
img1 | character varying(100) |
slug | character varying(50) |
created | date | not null
modified | date | not null
ppsn | character varying(20) |
Indexes:
"employee_pkey" PRIMARY KEY, btree (id)
"employee_slug_key" UNIQUE, btree (slug)
"employee_slug_like" btree (slug varchar_pattern_ops)
Referenced by:
TABLE "employeedynamic" CONSTRAINT "employee_id_refs_id_71e22023" FOREIGN KEY (employee_id) REFERENCES employee(id) DEFERRABLE INITIAL
LY DEFERRED
TABLE "drvliclicence" CONSTRAINT "employee_id_refs_id_afc65012" FOREIGN KEY (employee_id) REFERENCES employee(id) DEFERRABLE INITIALLY
DEFERRED
TABLE "coursedetail_attendance" CONSTRAINT "employee_id_refs_id_c8466b5f" FOREIGN KEY (employee_id) REFERENCES employee(id) DEFERRABLE
INITIALLY DEFERRED
.
=# select a.name from employee a where a.id = 366;
(366,Tommy,Gibbons,"",1800-08-21,1002180,images/GibbonsT2010_1.
(1 row)
Problem: How is a.name returning these details?
I've tried looking up aliases and triggers but I cannot figure this.
Check trigger:
=# \dft
List of functions
Schema | Name | Result data type | Argument data types | Type
--------+------+------------------+---------------------+------
(0 rows)
or
=# SELECT tgname FROM pg_trigger, pg_class WHERE tgrelid=pg_class.oid and relname = 'employee';
RI_ConstraintTrigger_101722
RI_ConstraintTrigger_101723
RI_ConstraintTrigger_101732
RI_ConstraintTrigger_101733
RI_ConstraintTrigger_101737
RI_ConstraintTrigger_101738
(6 rows)
Any idea how I can find what is causing a.name to return data?

See all indexes and appropriate columns for table

How to see all existed indexes for table? for example given table mytable, how to see his every index with appropriate columns?
Try this SQL
SELECT * FROM pg_indexes WHERE tablename = 'mytable';
In psql use the \d command:
postgres=> create table foo (id integer not null primary key, some_data varchar(20));
CREATE TABLE
postgres=> create index foo_data_idx on foo (some_data);
CREATE INDEX
postgres=> \d+ foo
Table "public.foo"
Column | Type | Modifiers | Storage | Stats target | Description
-----------+-----------------------+-----------+----------+--------------+------------
id | integer | not null | plain | |
some_data | character varying(20) | | extended | |
Indexes:
"foo_pkey" PRIMARY KEY, btree (id)
"foo_data_idx" btree (some_data)
Has OIDs: no
postgres=>
Other SQL tools have other means of displaying this information.