Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PostgreSQL约束排除不使用中的子查询选择_Sql_Postgresql_Constraints_Partition - Fatal编程技术网

PostgreSQL约束排除不使用中的子查询选择

PostgreSQL约束排除不使用中的子查询选择,sql,postgresql,constraints,partition,Sql,Postgresql,Constraints,Partition,在PostgreSQL中使用分区时,其中master是主分区表 CREATE TABLE master ( _id numeric, name character varying ); 有两个子表 分区1 CREATE TABLE partition_1 ( -- _id numeric, -- name character varying, CONSTRAINT partition_1_check CHECK (_id < 1000) ) INHERITS

在PostgreSQL中使用分区时,其中master是主分区表

CREATE TABLE master
(
  _id numeric,
  name character varying
);
有两个子表

分区1

CREATE TABLE partition_1
(
  -- _id numeric,
  -- name character varying,
  CONSTRAINT partition_1_check CHECK (_id < 1000)
)    
INHERITS (master);
CREATE INDEX partition_1_id_idx
  ON partition_1
  USING btree
  (_id);
以及本例中某些ID(1,3)的表

CREATE TABLE _ids
(
_id numeric NOT NULL,
CONSTRAINT ids_pkey PRIMARY KEY (_id)
)
声明

EXPLAIN SELECT * FROM master WHERE _id IN (SELECT * FROM _ids)
生成两个分区的seq扫描,不管_id是否包含分区_1/2中的元素

Hash Semi Join  (cost=39.48..141.14 rows=2621 width=14)
  Hash Cond: (master._id = _ids._id)
  ->  Append  (cost=0.00..62.00 rows=4001 width=14)
        ->  Seq Scan on master  (cost=0.00..0.00 rows=1 width=14)
        ->  Seq Scan on partition_1  (cost=0.00..30.98 rows=1998 width=13)
        ->  Seq Scan on partition_2  (cost=0.00..31.02 rows=2002 width=15)
  ->  Hash  (cost=23.10..23.10 rows=1310 width=32)
        ->  Seq Scan on _ids  (cost=0.00..23.10 rows=1310 width=32)
如果我改用

SELECT * FROM master WHERE _id IN (1,3) 
我得到了期望的结果:

Append  (cost=0.00..17.40 rows=5 width=13)
  ->  Seq Scan on master  (cost=0.00..0.00 rows=1 width=14)
        Filter: (_id = ANY ('{1,3}'::numeric[]))
  ->  Bitmap Heap Scan on partition_1  (cost=8.59..17.40 rows=4 width=13)
        Recheck Cond: (_id = ANY ('{1,3}'::numeric[]))
        ->  Bitmap Index Scan on partition_1_id_idx  (cost=0.00..8.58 rows=4 width=0)
              Index Cond: (_id = ANY ('{1,3}'::numeric[]))
如何让PostgreSQL正确使用约束排除


注意:我将constraint\u exclusion设置为partition

这对于注释来说太长了

在Postgres编译该查询时选择分区。当您使用常量时,引擎就会知道数据所在的位置。当您使用子查询时,Postgres不知道


因此,使用子查询会阻止引擎利用分区。

这对于注释来说太长了

在Postgres编译该查询时选择分区。当您使用常量时,引擎就会知道数据所在的位置。当您使用子查询时,Postgres不知道


因此,使用子查询可以防止引擎利用分区。

AFAIK,这是一个很好的答案。除了关于查询计划器的注释外,即使文档也没有进一步说明这一点:在启用约束排除的情况下,计划器将检查每个分区的约束,并尝试证明该分区不需要扫描,因为它不能包含任何符合查询WHERE子句的行。当计划者能够证明这一点时,它会将分区从查询计划中排除。(这基本上就是您所写的:如果这依赖于其他列/子查询等,则无法证明任何事情)。您知道如何执行更好的查询以利用约束吗?也许是某种形式的嵌套查询?好吧,这是一个完美的答案。除了关于查询计划器的注释外,即使文档也没有进一步说明这一点:在启用约束排除的情况下,计划器将检查每个分区的约束,并尝试证明该分区不需要扫描,因为它不能包含任何符合查询WHERE子句的行。当计划者能够证明这一点时,它会将分区从查询计划中排除。(这基本上就是您所写的:如果这依赖于其他列/子查询等,则无法证明任何事情)。您知道如何执行更好的查询以利用约束吗?也许是某种形式的嵌套查询?
Append  (cost=0.00..17.40 rows=5 width=13)
  ->  Seq Scan on master  (cost=0.00..0.00 rows=1 width=14)
        Filter: (_id = ANY ('{1,3}'::numeric[]))
  ->  Bitmap Heap Scan on partition_1  (cost=8.59..17.40 rows=4 width=13)
        Recheck Cond: (_id = ANY ('{1,3}'::numeric[]))
        ->  Bitmap Index Scan on partition_1_id_idx  (cost=0.00..8.58 rows=4 width=0)
              Index Cond: (_id = ANY ('{1,3}'::numeric[]))