postgresql - 如何在分区表上创建索引?

标签 postgresql indexing database-partitioning postgresql-11

如何在 PostgreSQL 11.2 中为分区表创建索引?

我的 table 是:

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;

如您所见,testtable_unique_pkey 是我的索引。

但是当我运行时:

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

我看不到我的索引。

我检查了对我的查询的解释分析,它也没有使用索引。

最佳答案

基表的索引从来没有真正创建过,所以它不会出现在 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);

所以下面什么都不返回:

select *
from pg_indexes
where tablename = 'base_table';

但是它存储在 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';

返回:

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

但对于每个分区,索引将显示在 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);

然后:

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

返回:

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

2020-06-26 更新:

索引没有出现在 pg_indexes 中的事实被 Postgres 团队和 was fixed 确认为错误。在 Postgres 12 中。

所以上面的解释只对 Postgres 10 和 11 有效。从 Postgres 12 开始,base_table 上的索引将是 shown在`pg_indexes.

关于postgresql - 如何在分区表上创建索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55611209/

相关文章:

sql - 有可能 "Select N times"吗?

postgresql - Golang 为 "CREATE TABLE"准备语句

c++ - 返回 vector 最高值的前 5 个索引的函数

swift - ClosedRange<Int>.Swift 中 Int 的索引?

database-design - 何时使用水平分区,何时使用数据库分片?

sql - 在 MySQL 中对数据库表进行分区

sql - 我怎样才能避免 Postgres 中的这种三向死锁?

sql - PostgreSQL with-delete "relation does not exists"

elasticsearch - 有没有一种方法可以对现有数据启用_source?

sql - 如何尽可能透明地将现有的 Postgres 表迁移到分区表?