【发布时间】:2018-04-20 10:20:30
【问题描述】:
我有以下设置(简化摘录):
CREATE TABLE my_table (
ID VARCHAR(255) NOT NULL,
TENANT_ID CHAR(36) NOT NULL,
PRIMARY KEY (id)
);
-- creates a int hash of a string (> 0)
CREATE OR REPLACE FUNCTION h_int(text) RETURNS int as $$
SELECT @('x'||substr(md5($1),1,8))::bit(32)::int;
$$ language sql;
-- uses a numeric hash value to select a partition
CREATE OR REPLACE FUNCTION select_partition(text, int) RETURNS int as $$
SELECT h_int($1) % $2;
$$ language sql;
CREATE TABLE IF NOT EXISTS part_my_table_00 (
CONSTRAINT pk_part_00 PRIMARY KEY (ID),
CONSTRAINT ck_part_00 CHECK (select_partition(TENANT_ID, 2) = 0)
) INHERITS (my_table);
CREATE INDEX idx_tenant_ids_00 ON my_table (TENANT_ID);
CREATE TABLE IF NOT EXISTS part_my_table_01 (
CONSTRAINT pk_part_01 PRIMARY KEY (ID),
CONSTRAINT ck_part_01 CHECK (select_partition(TENANT_ID, 2) = 1)
) INHERITS (my_table);
CREATE INDEX idx_tenant_ids_01 ON my_table (TENANT_ID);
CREATE OR REPLACE FUNCTION fn_insert() RETURNS TRIGGER AS $$
declare
selectedPartition int;
tableName text := 'part_my_table_0';
queryString text;
BEGIN
selectedPartition := select_partition(NEW.TENANT_ID, 2);
tableName := tableName||selectedPartition;
queryString := 'INSERT INTO '||tableName||' SELECT($1).*';
EXECUTE queryString USING NEW;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER tr_insert BEFORE INSERT ON my_table
FOR EACH ROW EXECUTE PROCEDURE fn_insert();
SET constraint_exclusion = on;
现在插入效果很好。我的问题是约束排除似乎不适用于选择:
SELECT * FROM my_table WHERE TENANT_ID='anyVal';
解释此查询返回以下内容:
postgres=# EXPLAIN SELECT * FROM my_table WHERE TENANT_ID='anyVal';
QUERY PLAN
----------------------------------------------------------------------------------------------------------------
Append (cost=0.00..81.53 rows=11 width=6401)
-> Seq Scan on my_table (cost=0.00..0.00 rows=1 width=6401)
Filter: (tenant_id = 'bla'::bpchar)
-> Index Scan using idx_tenant_ids_00 on part_my_table_00 (cost=0.14..8.15 rows=1 width=6401)
Index Cond: (tenant_id = 'bla'::bpchar)
-> Index Scan using idx_tenant_ids_01 on part_my_table_01 (cost=0.14..8.15 rows=1 width=6401)
Index Cond: (tenant_id = 'bla'::bpchar)
我原以为只会扫描其中一个分区。有谁能帮帮我吗?
提前致谢!
【问题讨论】:
-
检查约束中的表达式与 where 子句中的表达式不匹配。
-
如何通过计算
WHERE tenant_id=**值的哈希来实现约束排除?
标签: sql postgresql postgresql-9.2 database-partitioning