【发布时间】:2014-07-01 08:05:58
【问题描述】:
我有以下数据库架构:
CREATE TABLE public.sgclasstab_id67
(
oid bigint NOT NULL,
att_1113 bigint,
att_1114 bigint,
att_1115 character varying(500),
att_1116 character varying(2000),
att_1578 double precision,
CONSTRAINT sgclasstab_id67_pkey PRIMARY KEY (oid)
)
CREATE TABLE public.sgclasstab_id68
(
oid bigint NOT NULL,
att_1119 bigint,
att_1139 bigint,
att_1496 character varying(2000),
CONSTRAINT sgclasstab_id68_pkey PRIMARY KEY (oid)
)
CREATE TABLE public.sggeofacelist
(
oid bigint NOT NULL,
meanid smallint,
numofislands smallint DEFAULT 0,
compound smallint DEFAULT 0,
extra character varying(512),
crs bigint DEFAULT (-1),
crsapp bigint DEFAULT (-1),
version bigint DEFAULT 0,
feature geometry,
CONSTRAINT sggeofacelist_pkey PRIMARY KEY (oid),
CONSTRAINT enforce_dims_feature CHECK (st_ndims(feature) = 3),
CONSTRAINT enforce_srid_feature CHECK (st_srid(feature) = 0)
)
CREATE TABLE public.sggeopointlist
(
oid bigint NOT NULL,
angle double precision,
meanid smallint,
crs bigint DEFAULT (-1),
crsapp bigint DEFAULT (-1),
origx double precision,
origy double precision,
feature geometry,
CONSTRAINT sggeopointlist_pkey PRIMARY KEY (oid),
CONSTRAINT enforce_dims_feature CHECK (st_ndims(feature) = 3),
CONSTRAINT enforce_srid_feature CHECK (st_srid(feature) = 0)
)
列 sgclasstab_id67.att_1114 引用表 sggeofacelist 中的几何,该表仅包含多边形,sgclasstab_id68.att_1139 列引用表 sggeopointlist 中的几何,该表仅包含点几何。两个表都可以包含数十万个几何图形,其中只有一小部分与上述表相关。所有几何都使用 GIST 索引。
现在,当我运行以下查询时
UPDATE sgclasstab_id68 SET att_1496 = (
SELECT t3943814704643.att_1115
FROM sgclasstab_id67 t3943814704643, sggeofacelist t3943863539361, sgclasstab_id68 t3943875447103, sggeopointlist t3943875522916
WHERE ((t3943814704643.att_1114=t3943863539361.oid ))
AND ((t3943875447103.att_1139=t3943875522916.oid ))
AND ((t3943863539361.feature && (t3943875522916.feature) AND ST_Intersects(t3943863539361.feature,(t3943875522916.feature))))
AND (t3943863539361.oid=t3943814704643.att_1114)
AND sgclasstab_id68.oid = t3943875447103.oid
LIMIT 1
)
它确实永远运行(我在 4 天后取消了它)。看看执行计划,这并不奇怪:
Update on sgclasstab_id68 (cost=0.00..1076.63 rows=100 width=736)
-> Seq Scan on sgclasstab_id68 (cost=0.00..1076.63 rows=100 width=736)
SubPlan 1
-> Limit (cost=0.70..10.48 rows=1 width=516)
-> Nested Loop (cost=0.70..10.48 rows=1 width=516)
-> Nested Loop (cost=0.55..10.18 rows=1 width=524)
-> Nested Loop (cost=0.29..9.33 rows=1 width=5482)
-> Seq Scan on sgclasstab_id67 t3943814704643 (cost=0.00..1.01 rows=1 width=524)
-> Index Scan using sggeofacelist_pkey on sggeofacelist t3943863539361 (cost=0.29..8.31 rows=1 width=4974)
Index Cond: (oid = t3943814704643.att_1114)
-> Index Scan using sggeopointlist_idx on sggeopointlist t3943875522916 (cost=0.27..0.84 rows=1 width=48)
Index Cond: ((t3943863539361.feature && feature) AND (t3943863539361.feature && feature))
Filter: _st_intersects(t3943863539361.feature, feature)
-> Index Scan using sgclasstab_id68a1139_idx on sgclasstab_id68 t3943875447103 (cost=0.14..0.29 rows=1 width=8)
Index Cond: (att_1139 = t3943875522916.oid)
Filter: (sgclasstab_id68.oid = oid)
如果我没有误读这里的任何内容,Postgres 首先执行交集,然后排除所有不被 sgclasstab_id68 中的对象引用的不相关几何。
交换这两个操作会不会更高效,或者我是否在这个查询中做了一些事情来使这个选项不可用?如果没有,有没有办法强制 Postgres 重新考虑?
PostgreSQL 9.3,PostGIS 2.1.1 r12113。
提前致谢(对于难以阅读的查询,我们深表歉意,它是自动生成的)。
【问题讨论】:
-
请在查询中为表使用别名。不可读。
-
我认为你的意思是不要使用像 t3943863539361 这样的别名,不是吗:D
-
您实际上并不需要 && 边界框检查,因为 ST_Intersects 暗示了它。如果你删除它,并将 t3943863539361 重命名为 poly 等,调试起来会更容易。但是,首先想到的是您的空间索引没有被使用,因为在解释输出中没有使用
进行索引扫描。 -
顺便说一句,
AND sgclasstab_id68.oid = t3943875447103.oid将列与自身进行比较,可能是“框架”的错字? (产生一个笛卡尔积) -
@JohnBarça 哦,你是对的。但如果没有别名,它仍然无法阅读。
标签: sql postgresql postgis