在PostGIS中定义点时,何时决定使用以下哪个?


ST_SetSRID(ST_MakePoint(lon,lat),4326)
ST_SetSRID(ST_Point(long,lat),4326)
ST_SetSRID(ST_GeomFromText('POINT(lon lat)',4326)
ST_GeomFromEWKT('SRID=4326;POINT(lon lat)')

如果本质上存在性能差异,那将是最快的?

评论

看看这个答案:gis.stackexchange.com/a/285017/6052

#1 楼

我的猜测是ST_MakePoint最快,但这很容易用10万个随机点进行基准测试。

\timing

WITH test AS (
  SELECT <POINT CONSTRUCTOR METHOD>
  FROM generate_series(1,100000)
)
SELECT count(*) FROM test;


这是PostgreSQL上PostGIS 2.1(trunk)的一些结果9.1,x64 Debian。我做了几次,以获得一个近似的平均值。以下是从最快到最慢的<POINT CONSTRUCTOR METHOD>



ST_SetSRID(ST_MakePoint(random(), random()), 4326)

avg 160 ms
最快,并且保留两倍点精度(无损)
使用数字坐标数据进行参数化查询的最简单方法



ST_GeomFromText('POINT(' || random()::text || ' ' || random()::text || ')', 4326)

平均760毫秒
很慢,因为将数字强制转换为文本,然后将字符串拼凑在一起,然后PostGIS需要对其进行解析以找到数字
,因为数字->文本->数字转换



ST_GeomFromEWKT('SRID=4326;POINT(' || random()::text || ' ' || random()::text || ')')

平均810毫秒
最慢,不确定为什么它比ST_GeomFromText





最后,关于上述方法的无损/有损转换之间的区别,我们只做了一个简短的脚注。只有ST_MakePoint保留二进制浮点精度数据,并且文本转换将数据的一小部分截断。尽管两个点可能具有二进制差异(在WKB中可见),但它们在空间上应始终相等。距离差本质上是双精度的机器epsilon。

SELECT
  (geom_text = geom_binary) AS spatially_equal,
  (geom_text::text = geom_binary::text) AS binary_equal,
  (ST_AsText(geom_text) = ST_AsText(geom_binary)) AS wkt_equal,
  ST_Distance(geom_text, geom_binary)
FROM (
  SELECT x, y,
    ST_GeomFromText('POINT(' || x::text || ' ' || y::text || ')') AS geom_text,
    ST_MakePoint(x, y) AS geom_binary
  FROM (SELECT random()::float8 as x, random()::float8 as y) AS f1
) AS f2;

 spatially_equal | binary_equal | wkt_equal |     st_distance
-----------------+--------------+-----------+----------------------
 t               | f            | t         | 1.38777878078145e-16


评论


感谢您提供有关如何计算此值的详细说明。我对SQL语法感到好奇。只是伪代码是指四种不同的方法,还是您正在执行某种功能?

– djq
13年4月21日在19:20



@djq是的,它只是1、2和3中实际SQL代码的占位符。

– Mike T
13年4月21日在20:01

有关用作参考的float数据类型的精度限制的详细信息...机器epsilon为〜1e-14 ...将f1表更改为FROM(将SELECT random():: float8设置为x,将random():: float8设置为y UNION) SELECT 12.24343484842,34.58384538483434)AS f1在您的psql中看到它。

– Peter Krauss
18-09-14在7:31

#2 楼

ST_MakePoint和ST_Point相同-它们都调用LWGEOM_makepoint(您可以在源代码的postgis / postgis.sql.in文件中看到此信息)。我会使用ST_MakePoint。文本转换例程产生相同的结果,但由于需要大量的解析,因此速度较慢。

#3 楼

SRID 4326和几何

作为MikeT出色,全面和最新答案的补充说明。很多人似乎是在问这个问题,因为他们想在POINT列上设置SRID。

CREATE TABLE foo ( geom geometry(Point,4326) );


但是当他们这样做时,他们遇到了看起来最好的问题。创建点的方法,可惜他们遇到了麻烦。

INSERT INTO foo (geom) VALUES ( ST_MakePoint(1,2) );
ERROR:  Geometry SRID (0) does not match column SRID (4326);


从那里开始,他们认为它们有两个选择


手动设置SRID,ST_SetSRID( ST_MakePoint(1,2) )是最右边的方法,但又很麻烦,或者使用ST_GeomFromText从文本构造,这从逻辑上讲比较慢,不需要基准:PostgreSQL必须从文本中解析构造函数的参数。它本身也非常丑陋。

A,还有另一种方法。

地理类型

geography的默认SRID为4326。如果是新用户,我建议使用geography而不是geometry。实际上,通常,如果您不知道两者之间的差异,则可能需要geography。您可以轻松切换列。

BEGIN;
  ALTER TABLE foo ADD COLUMN geog geography(point,4326);
  UPDATE foo SET geog = geom::geography;
  ALTER TABLE foo DROP COLUMN geom;
COMMIT;


现在插入更加容易,因为该类型已经与SRID 4326进行了默认关联。现在,您可以显式转换为geography,或者只是让隐式强制转换工作

ST_MakePoint(x,y)                     -- implicit cast and srid
ST_MakePoint(x,y)::geography          -- explicit cast, implicit srid
ST_SetSRID( ST_MakePoint(3,4), 4326 ) -- explicit cast and srid


看起来像这样,(它们都插入相同的东西)

INSERT INTO foo (geog) VALUES
  -- implicit cast and SRID
  ( ST_MakePoint(1,2) ),

  -- explicit cast, implicit SRID
  ( ST_MakePoint(1,2)::geography ),

   -- explicit cast and SRID
  ( ST_SetSRID( ST_MakePoint(3,4), 4326 )::geography );

< br转换为文本,然后强制PostgreSQL使用
ST_GeomFromTextST_GeogFromText解析文本是愚蠢且缓慢的。