我有两个表:一个是基于有效时间的分区表,第二个是具有有效时间和到期时间的状态表。我也有一个视图,该视图将状态表连接到分区表,并尝试将分区表的搜索范围缩小到仅那些尚未过期的分区。
我尝试使用单独的validtime列,因此where子句中的那个不与分区中的那个绑定,但是查询计划程序仅在那些情况下才对几何显示索引扫描,并且仍然对分区上的索引进行扫描不能根据有效期限包含有效结果。
分区表如下:
CREATE TABLE public.poly__20190609__171000
(
-- Inherited from table poly: ogc_featureid bigint NOT NULL DEFAULT nextval('poly_ogc_featureid_seq'::regclass),
-- Inherited from table poly: validtime timestamp without time zone,
-- Inherited from table poly: geometry_4326 geometry(Polygon,4326) NOT NULL,
CONSTRAINT poly_20190609_171000_pkey PRIMARY KEY (ogc_featureid),
CONSTRAINT poly_20190609_171000_check CHECK (validtime >= '2019-06-09 17:10:00'::timestamp without time zone AND validtime <= '2019-06-09 17:14:59'::timestamp without time zone)
);
CREATE INDEX poly__20190609__171000_4326_gist
ON public.poly__20190609__171000
USING gist
(geometry_4326);
CREATE INDEX poly__20190609__171000_validtime_idx
ON public.poly__20190609__171000
USING btree
(validtime);
状态表如下:
CREATE TABLE public.poly_current_state
(
validtime timestamp without time zone NOT NULL,
current_expiration timestamp without time zone NOT NULL,
CONSTRAINT poly_current_state_pkey PRIMARY KEY (validtime)
);
视图如下:
CREATE VIEW public.example_view AS
SELECT p.ogc_featureid,
pcs.validtime,
pcs.current_expiration AS expiration,
p.geometry_4326
FROM poly_current_state pcs
INNER JOIN poly p ON p.validtime = pcs.validtime;
查询示例如下:
SELECT "expiration","validtime"
FROM "public"."example_view"
WHERE (
"validtime" < '2019-06-09T18:30:00Z'
AND "expiration" > '2019-06-09T18:00:00Z'
AND ST_DWithin("geometry_4326",ST_GeomFromText('MULTILINESTRING ((-130 35, -65 35))', 4326),3.3333333333333335)
) LIMIT 1;
查询的解释(为了保护无辜的二进制几何被截断)如下所示(请注意,在到期前很长一段时间(有效时间之后最多15分钟)内包含前两行有效):
Limit (cost=0.05..11.25 rows=1 width=16)
-> Nested Loop (cost=0.05..274278.59 rows=24506 width=16)
-> Append (cost=0.00..268347.87 rows=92105 width=11)
-> Seq Scan on poly p (cost=0.00..0.00 rows=1 width=20)
Filter: ((validtime < '2019-06-09 18:30:00'::timestamp without time zone) AND (geometry_4326 && '010300002...'::geometry) AND ('01050000...'::geometry && st_expand(geometry_4326, 3.33333333333333::double precision)) AND
-> Bitmap Heap Scan on poly__20190609__151500 p_1 (cost=845.99..6160.40 rows=2037 width=11)
Recheck Cond: (geometry_4326 && '010300002...'::geometry)
Filter: ((validtime < '2019-06-09 18:30:00'::timestamp without time zone) AND ('01050000...'::geometry && st_expand(geometry_4326, 3.33333333333333::double precision)) AND _st_dwithin(geometry_4326, '01050000...'::geomet
-> Bitmap Index Scan on poly__20190609__151500_4326_gist (cost=0.00..845.89 rows=30553 width=0)
Index Cond: (geometry_4326 && '010300002...'::geometry)
-> Bitmap Heap Scan on poly__20190609__152000 p_2 (cost=870.03..6217.87 rows=2039 width=11)
Recheck Cond: (geometry_4326 && '010300002...'::geometry)
Filter: ((validtime < '2019-06-09 18:30:00'::timestamp without time zone) AND ('01050000...'::geometry && st_expand(geometry_4326, 3.33333333333333::double precision)) AND _st_dwithin(geometry_4326, '01050000...'::geomet
-> Bitmap Index Scan on poly__20190609__152000_4326_gist (cost=0.00..869.92 rows=30579 width=0)
Index Cond: (geometry_4326 && '010300002...'::geometry)
...
-> Bitmap Heap Scan on poly__20190609__182500 p_39 (cost=1159.25..7559.40 rows=2803 width=11)
Recheck Cond: (geometry_4326 && '010300002...'::geometry)
Filter: ((validtime < '2019-06-09 18:30:00'::timestamp without time zone) AND ('01050000...'::geometry && st_expand(geometry_4326, 3.33333333333333::double precision)) AND _st_dwithin(geometry_4326, '01050000...'::geomet
-> Bitmap Index Scan on poly__20190609__182500_4326_gist (cost=0.00..1159.11 rows=42039 width=0)
Index Cond: (geometry_4326 && '010300002...'::geometry)
-> Index Only Scan using poly_current_state_a_idx on poly_current_state pcs (cost=0.05..0.06 rows=1 width=19)
Index Cond: ((validtime = p.validtime) AND (current_expiration > '2019-06-09 18:00:00'::timestamp without time zone))
我正在使用Postgres 9.3(我知道,但是升级不是即时选择)。