在我的测试中,ST_DWithin比ST_Intersects更快。这是令人惊讶的,特别是因为准备好的几何算法应该在这种情况下起作用。我认为这有可能比我在这里显示的要快得多。
我做了一些测试,发现两件事几乎使速度提高了一倍。首先,我尝试使用较新的计算机,但仍然是一台非常普通的笔记本电脑,也许除了SATA3 ssd -disks以外。
然后,下面的查询用了18秒,而不是旧笔记本电脑上的62秒。接下来,我发现在写点表上的索引不是必需的之前我是完全错误的。有了该索引,ST_Intersects的表现就达到了预期,事情变得非常快。我将点数表中的点数增加到100万,并进行了查询:
CREATE TABLE points_ct AS
SELECT imported_ct.gid as ct_gid, t.gid as point_id
FROM imported_ct , t WHERE ST_Intersects(imported_ct.geom , t.geom);
在72秒内运行。由于存在1249个多边形,因此在72秒内完成了1249000000个测试。每秒约进行17000000次测试。或每秒对所有多边形测试近14000点。
从该测试中,您要测试的400000000点应大约花费8个小时,而将负载分配到多个内核没有任何麻烦。PostGIS永不停止打动我:-)
首先,要可视化结果,可以将点几何添加到结果表中,例如在QGIS中将其打开,并在imported_ct字段上使用唯一值设置其样式。
其次,是的,您还可以通过使用右(或左)连接来获得落在任何多边形之外的点,如下所示:
CREATE TABLE points_ct AS
SELECT imported_ct.gid as ct_gid, t.gid as point_id
FROM imported_ct right join t ON ST_Intersects(imported_ct.the_geom , t.geom);
我做了一些测试来验证PostGIS是否可能。
首先,我不明白。每行有两个点。两个点始终都在同一多边形中吗?这样就可以对其中一个点进行计算了。如果它们可以位于两个不同的多边形中,则需要一种将一个点行连接到两个多边形的方法。
从测试来看,这似乎可行,但是您可能需要一些创造性的解决方案才能将负载分散到多个cpu内核上。
我在一台具有双核centrino cpu(我认为约为2.2GHz),2GB RAM的4岁笔记本电脑上进行了测试。如果您有48个BG RAM,我想您的CPU能力也会更高。
我要做的是创建一个具有100000点的随机点表,如下所示:
CREATE TABLE t AS
WITH r AS
(SELECT ST_Extent(the_geom)::geometry ext FROM imported_ct)
SELECT ST_Point(x,y) AS geom FROM
(SELECT GENERATE_SERIES(1,100000)) s,
(SELECT ST_Xmin(ext)+(random()*(ST_Xmax(ext)-ST_Xmin(ext))) x, ST_Ymin(ext)+(random()*(ST_Ymax(ext)-ST_Ymin(ext))) y FROM r
) f;
然后添加一个如下的gid:
ALTER TABLE t ADD COLUMN GID SERIAL;
然后运行:
CREATE TABLE points_ct AS
SELECT imported_ct.gid as ct_gid, t.gid as point_id FROM imported_ct , t WHERE ST_Dwithin(imported_ct.the_geom , t.geom,0);
大约需要62秒(与相同点数的ArcGIS结果进行比较)。结果是一个表格,该表格将我的表格t中的点与表格中具有普查区域的gid相连接。
以这种速度,您将在大约34小时内完成200磨点。因此,如果只需检查其中一项就足够了,那么我的旧笔记本电脑就可以使用一个内核来做到这一点。
但是,如果您需要检查这两点,可能会更困难。
然后,您可以通过针对数据库启动多个会话并运行不同的查询,将负载手动分配给多个内核。
在我的示例中,使用50000点和两个cpu内核,我尝试过:
CREATE TABLE t1 as
SELECT imported_ct.gid as ct_gid, t.gid as point_id FROM imported_ct , t WHERE t.gid >50000 and ST_Dwithin(imported_ct.the_geom , t.geom,0);
在一个数据库会话上同时运行:
CREATE TABLE t2 as
SELECT imported_ct.gid as ct_gid, t.gid as point_id FROM imported_ct , t WHERE t.gid <=50000 and ST_Dwithin(imported_ct.the_geom , t.geom,0);
在另一个数据库会话上。
这花了大约36秒,因此它可能比第一个示例慢一点,这可能取决于同时写入光盘。但是由于bith核心在同一时间工作,所以我花的时间不超过36秒。
要尝试合并表t1和t2:
CREATE TABLE t3 AS
SELECT * FROM t1
UNION ALL
SELECT * FROM t2;
用大约半秒钟。
因此,使用较新的硬件并在许多内核上分配负载,即使现实世界比测试案例要慢,这绝对应该是可能的。
可能值得注意的是该示例来自Linux(Ubuntu)。使用Windows将是另一回事。但是我还有所有其他日常应用程序正在运行,因此笔记本电脑以前的负载非常重。这样也许可以很好地模拟Windows情况,而无需打开pgadmin。