Die*_*ipe 5 postgresql performance spatial postgis query-performance
我在尝试改进两个空间表之间的交集时遇到了困难,我想收到有关表设计、查询或 dba 配置的任何提示。
表现在teste.recorte_grade
有 1,655,569 行,但这是为 900 万行表的测试制作的子样本。
CREATE TABLE teste.recorte_grade
(
id integer NOT NULL DEFAULT nextval('teste."Recorte_grade_id_seq"'::regclass),
id_gre character varying(21),
indice_gre character varying(16),
the_geom geometry(Polygon),
CONSTRAINT "Recorte_grade_pkey" PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
CREATE INDEX sidx_recorte_grade_geom
ON teste.recorte_grade
USING gist
(the_geom);
Run Code Online (Sandbox Code Playgroud)
表teste2.uso_2012
有 177,888 行,这是它将永远拥有的所有数据。
CREATE TABLE teste2.uso_2012
(
id integer NOT NULL,
gridcode smallint NOT NULL,
geom geometry(MultiPolygon) NOT NULL,
CONSTRAINT pk_id_uso_2012 PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
CREATE INDEX idx_hash_calsse_uso_2012_teste2
ON teste2.uso_2012
USING hash
(gridcode);
CREATE INDEX sidx_uso_2012_geom_teste2
ON teste2.uso_2012
USING gist
(geom);
Run Code Online (Sandbox Code Playgroud)
我想要的只是gridcode
两个表之间每个交集的面积和,基本上是这个查询的结果:
Select grade.id, uso.gridcode, , st_area(st_intersection(grade.the_geom, uso.geom))
from teste2.uso_2012 as uso
inner join teste.recorte_grade as grade on ST_Intersects(grade.the_geom, uso.geom) = 't'
order by grade.id
Run Code Online (Sandbox Code Playgroud)
然而,当我决定取消它的执行时,这个查询运行了大约16 个小时没有任何结果。如果子样本花了这么长时间,想象一下完整的数据集。
两个表之前都进行了真空分析。
EXPLAIN
对于慢查询:http : //explain.depesz.com/s/PEV
我认为gridcode
每次在多个查询中将其分开可能是个好主意。这就是我创建哈希索引的原因。
这是teste2.uso_2012
表中的数据分布:
CREATE TABLE teste.recorte_grade
(
id integer NOT NULL DEFAULT nextval('teste."Recorte_grade_id_seq"'::regclass),
id_gre character varying(21),
indice_gre character varying(16),
the_geom geometry(Polygon),
CONSTRAINT "Recorte_grade_pkey" PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
CREATE INDEX sidx_recorte_grade_geom
ON teste.recorte_grade
USING gist
(the_geom);
Run Code Online (Sandbox Code Playgroud)
以下是个人的一些查询结果gridcodes
:
Select grade.id, uso.gridcode, st_area(st_intersection(grade.the_geom, uso.geom)) from teste.recorte_2012 as uso inner join teste.recorte_grade as grade on ST_Intersects(grade.the_geom, uso.geom) = 't' where uso.gridcode = 1
--11 seconds
--10,069 rows retrieved
--http://explain.depesz.com/s/tZV1
Select grade.id, uso.gridcode, st_area(st_intersection(grade.the_geom, uso.geom)) from teste.recorte_2012 as uso inner join teste.recorte_grade as grade on ST_Intersects(grade.the_geom, uso.geom) = 't' where uso.gridcode = 2
--3275 seconds
--200,682 rows retrieved
Select grade.id, uso.gridcode, st_area(st_intersection(grade.the_geom, uso.geom)) from teste2.uso_2012 as uso inner join teste.recorte_grade as grade on ST_Intersects(grade.the_geom, uso.geom) = 't' where uso.gridcode = 2
--Total query runtime: 3333 seconds
--200,682 rows retrieved.
Select grade.id, uso.gridcode, st_area(st_intersection(grade.the_geom, uso.geom)) from teste.recorte_2012 as uso inner join teste.recorte_grade as grade on ST_Intersects(grade.the_geom, uso.geom) = 't' where uso.gridcode = 10
--5 hours without result
Run Code Online (Sandbox Code Playgroud)
teste.recorte_2012
并且teste2.uso_2012
几乎是同一张表,其中uso_2012
少了 1 列。
如您所见,这似乎不太有希望。是否有任何建议可以加快此过程?
我正在考虑创建一个存储过程来循环 177,888 行并直接获取每行的交集和面积。这是一个好主意吗?
服务器在其他数据库之间共享,但在我运行查询的同时没有并行运行繁重的进程。
我有一些非常复杂的特殊功能,几乎有 10 万个顶点。关于 Postgres 版本,只有 DBA 可以更新基础设施,而我不是其中之一。
自本文发布以来,问题不断发展,现在我们处理 140kk+ 行。然而,Postgis 也在不断发展,现在可以“修复”特征表。不再需要Dice
ArcMap。
我使用ST_VoronoiPolygons方法完成此操作。我创建了一个工作要点,其中包含一个函数,该函数可以将原始表上的特征分解为可行的大小以进行处理。
\n\n有关信息,我可以使用其他工具并分配工作量来完成此操作:
\n\n现在,此过程“仅”需要 3 个小时即可完成。
\n\n很ST_Intersects
轻。问题是这个计算:
st_area(st_intersection(grade.the_geom, uso.geom)).\n
Run Code Online (Sandbox Code Playgroud)\n\n构建复杂特征的交集并计算面积是一项艰巨的任务。
\n