postgres indexing all columns of composite primary key - postgresql

in postgres, just checking if we need to index all columns of composite primary key
CREATE TABLE BOOK_TYPE(
ID TEXT NOT NULL,
TYPE TEXT NOT NULL,
LABELS HSTORE NOT NULL,
CONSTRAINT BOOK_TYPE_PKEY PRIMARY KEY (ID,TYPE)
);
should I have to index ID and type separately?

You don't need to create any extra index unless you happen to need it to speed up a query. The primary key will automatically create a unique index on (id, type), and that is all that is needed to guarantee consistency.

Related

unique constraint to a foreign table

I have two tables, experiment and sample. Samples must be unique within experiments of the same type, but can be shared between experiments that have a different type. I understand how I can add a unique constraint to the samples to make them always unique, but is it possible to create a unique constraint based on the information in the foreign table?
create table experiment (
id integer primary key,
name text,
type text
);
create table sample (
id integer primary key,
name text,
experiment_id integer,
);
alter table sample add constraint exp_fkey foreign key (experiment_id) references experiment(id);
You can create a (redundant) unique constraint on experiment (id, type), add type to sample, create a foreign key constraint from (experiment_id, type) to (id, type) and a unique constraint on sample.type.

Table with SERIAL field gets indexes automatically in PostgreSQL?

I am working on a database and I need to add indexes to it.
I have a table like this.
CREATE TABLE Customers
(
Id SERIAL PRIMARY KEY,
FirstName CHARACTER VARYING(30),
LastName CHARACTER VARYING(30),
Email CHARACTER VARYING(30),
Age INTEGER
);
CREATE UNIQUE INDEX customers_idx ON Customers (Id);
Do I need to add indexes to it if there is a field with the SERIAL attribute?
As per the documentation,
Adding a primary key will automatically create a unique B-tree index on the column or group of columns listed in the primary key, and will force the column(s) to be marked NOT NULL.
So no, in this case you do not need to create the customers_idx yourself, because you defined that column as a primary key. However, the serial type itself (if the column isn't a primary key or unique) does NOT automatically come with an index.

Citus: How can I add self referencing table in distributed tables list

I'm trying to run create_distributed_table for tables which i need to shard and almost all of the tables have self relation ( parent child )
but when I run SELECT create_distributed_table('table-name','id');
it throws error cannot create foreign key constraint
simple steps to reproduce
CREATE TABLE TEST (
ID TEXT NOT NULL,
NAME CHARACTER VARYING(255) NOT NULL,
PARENT_ID TEXT
);
ALTER TABLE TEST ADD CONSTRAINT TEST_PK PRIMARY KEY (ID);
ALTER TABLE TEST ADD CONSTRAINT TEST_PARENT_FK FOREIGN KEY (PARENT_ID) REFERENCES TEST (ID);
ERROR
citus=> SELECT create_distributed_table('test','id');
ERROR: cannot create foreign key constraint
DETAIL: Foreign keys are supported in two cases, either in between two colocated tables including partition column in the same ordinal in the both tables or from distributed to reference tables
For the time being, it is not possible to shard a table on PostgreSQL without dropping the self referencing foreign key constraints, or altering them to include a separate and new distribution column.
Citus places records into shards based on the hash values of the distribution column values. It is most likely the case that the hashes of parent and child id values are different and hence the records should be stored in different shards, and possibly on different worker nodes. PostgreSQL does not have a mechanism to create foreign key constraints that reference records on different PostgreSQL clusters.
Consider adding a new column tenant_id and adding this column to the primary key and foreign key constraints.
CREATE TABLE TEST (
tenant_id INT NOT NULL,
id TEXT NOT NULL,
name CHARACTER VARYING(255) NOT NULL,
parent_id TEXT NOT NULL,
FOREIGN KEY (tenant_id, parent_id) REFERENCES test(tenant_id, id),
PRIMARY KEY (tenant_id, id)
);
SELECT create_distributed_table('test','tenant_id');
Note that parent and child should always be in the same tenant for this to work.

Automatically created indexes in postgresql: combined index on key attributes?

I'm not sure which indexes postgresql AUTOMATICALLY creates; I think it will create one on Book(ibsn), because its the primary key, and also Book(title), because its a candidate key... but I'm not sure if postgres will automatically create a combined index on all key attributes Book(ibsn, title). Also, would it create any other indexes automatically?
CREATE TABLE Book (
isbn INTEGER CONSTRAINT B_ISBN CHECK (ISBN BETWEEN 1 AND 2000),
title VARCHAR(200) CONSTRAINT B_TITLE NOT NULL UNIQUE,
author VARCHAR(50) CONSTRAINT B_AUTH NOT NULL,
cost FLOAT DEFAULT 0.00,
lent_date DATE,
returnDate DATE,
times_lent INTEGER,
sectionID SMALLINT,
CONSTRAINT BOOK_PRIME PRIMARY KEY (isbn),
CONSTRAINT BOOK_SECT FOREIGN KEY (sectionID) REFERENCES Section(sectionID) ON DELETE CASCADE
);
Postgres will automatically create indexes only for:
primary keys: Adding a primary key will automatically create a unique B-tree index on the column or group of columns listed in the primary key
unique constraints: Adding a unique constraint will automatically create a unique B-tree index on the column or group of columns listed in the constraint
In your case, Postgres creates one unique index on the column isbn and one unique index on the column unique because you declared each column individually to be unique, not the combination of both.
No other indexes will be created automatically.

Will a primary key index serve as an index for a foreign key when fk columns are subset of pk?

I have a table where part of the primary key is a foreign key to another table.
create table player_result (
event_id integer not null,
pub_time timestamp not null,
name_key varchar(128) not null,
email_address varchar(128),
withdrawn boolean not null,
place integer,
realized_values hstore,
primary key (event_id, pub_time, name_key),
foreign key (email_address) references email(address),
foreign key (event_id, pub_time) references event_publish(event_id, pub_time));
Will the index generated for the primary key suffice to back the foreign key on event_id and pub_time?
Yes.
Index A,B,C
is good for:
A
A,B
A,B,C (and any other combination of the full 3 fields, if default order is unimportant)
but not good for other combinations (such as B,C, C,A etc.).
It will be useful for the referencing side, such that a DELETE or UPDATE on the referenced table can use the PRIMARY KEY of the referencing side as an index when performing checks for the existence of referencing rows or running cascade update/deletes. PostgreSQL doesn't require this index to exist at all, it just makes foreign key constraint checks faster if it is there.
It is not sufficient to serve as the unique constraint for a reference to those columns. You couldn't create a FOREIGN KEY that REFERENCES player_result(event_id, pub_time) because there is no unique constraint on those columns. That pair can appear multiple times in the table so long as each pair has a different name_key.
As #xagyg accurately notes, the unique b-tree index created by the foreign key reference is also only useful for references to columns from the left of the index. It could not be used for a lookup of pub_time, name_key or just name_key, for example.