Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create index on table which is partitioned?

How to create an index on a partitioned table in PostgreSQL 11.2?

My table is:

CREATE TABLE sometablename
(
    column1 character varying(255) COLLATE pg_catalog."default" NOT NULL,
    column2 integer NOT NULL,
    column3 character varying(255) COLLATE pg_catalog."default" NOT NULL,
    "timestamp" timestamp without time zone NOT NULL,
    avg_val double precision,
    max_val double precision,
    min_val double precision,
    p95_val double precision,
    sample_count double precision,
    sum_val double precision,
    unit character varying(255) COLLATE pg_catalog."default",
    user_id bigint NOT NULL,
    CONSTRAINT testtable_pkey PRIMARY KEY (column1, column2, column3, "timestamp", user_id)
)
PARTITION BY HASH (user_id) 
    WITH (
    OIDS = FALSE
)
TABLESPACE pg_default;


CREATE UNIQUE INDEX testtable_unique_pkey
ON sometablename USING btree (column1 COLLATE pg_catalog."default", column2
COLLATE pg_catalog."default", "timestamp", user_id)
TABLESPACE pg_default;

As you can see testtable_unique_pkey is my index.

but when I run:

SELECT tablename, indexname, indexdef 
FROM pg_indexes 
WHERE tablename = 'sometablename'

I can't see my index.

I checked the explain analysis on my queries which is also not using the index.

like image 234
Dhanraj Avatar asked Apr 10 '19 11:04

Dhanraj


People also ask

How do you create an index on a partitioned table?

You can create bitmap indexes on partitioned tables, with the restriction that the bitmap indexes must be local to the partitioned table. They cannot be global indexes. Global indexes can be unique. Local indexes can only be unique if the partitioning key is a part of the index key.

Can we CREATE INDEX on partitioned table in SQL Server?

The following semantics apply when using the CREATE INDEX statement for partitioned tables: The partition specified in the FOR PARTITION clause must be an existing partition in the table. Partitions can be specified in any order.

Do we need index on partitioned column?

(The key index is not strictly necessary, but in most scenarios it is helpful.) This automatically creates a matching index on each partition, and any partitions you create or attach later will also have such an index.

Can partition be indexed?

A partitioned index is made up of a set of index partitions, each of which contains the index entries for a single data partition. Each index partition contains references only to data in its corresponding data partition. Both system- and user-generated indexes can be partitioned.


1 Answers

The index for the base table is never really created, so it doesn't show up in pg_indexes:

CREATE TABLE base_table
(
    column1 varchar(255) NOT NULL,
    column2 integer NOT NULL,
    user_id bigint NOT NULL
)
PARTITION BY HASH (user_id);
CREATE UNIQUE INDEX idx_one ON base_table (column1, column2, user_id);

So the following returns nothing:

select *
from pg_indexes
where tablename = 'base_table';

It is however stored in pg_class:

select i.relname as indexname, t.relname as tablename
from pg_class i
  join pg_index idx on idx.indexrelid = i.oid
  join pg_class t on t.oid = idx.indrelid
where i.relkind = 'I'
  and t.relname = 'base_table';

returns:

indexname | tablename 
----------+-----------
idx_one   | base_table

But for each partition the index will show up in pg_indexes:

create table st_p1 partition of base_table for values with (modulus 4, remainder 0);
create table st_p2 partition of base_table for values with (modulus 4, remainder 1);
create table st_p3 partition of base_table for values with (modulus 4, remainder 2);
create table st_p4 partition of base_table for values with (modulus 4, remainder 3);

And then:

select tablename, indexname
from pg_indexes
where tablename  in ('st_p1', 'st_p2', 'st_p3', 'st_p4');

returns:

tablename | indexname                        
----------+----------------------------------
st_p1     | st_p1_column1_column2_user_id_idx
st_p2     | st_p2_column1_column2_user_id_idx
st_p3     | st_p3_column1_column2_user_id_idx
st_p4     | st_p4_column1_column2_user_id_idx

Update 2020-06-26:

The fact that the index did not show up in pg_indexes was acknowledged as a bug by the Postgres team and was fixed in Postgres 12.

So the above explanation is only valid for Postgres 10 and 11. Starting with Postgres 12, the index on base_table will be shown in `pg_indexes.

like image 111
a_horse_with_no_name Avatar answered Oct 27 '22 10:10

a_horse_with_no_name