¿Qué función para crear un PUNTO en PostGIS?

28

Al definir un Punto en PostGIS, ¿cuándo decide utilizar cuál de los siguientes?

  • 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)')

Si es esencialmente una diferencia en el rendimiento, ¿cuál será la más rápida?

    
pregunta Nyxynyx 20.04.2013 - 03:56

3 respuestas

25

Supongo que ST_MakePoint es más rápido, pero esto es lo suficientemente fácil como punto de referencia con 100k puntos aleatorios.

\timing

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

Y aquí hay algunos resultados con PostGIS 2.1 (troncal) en PostgreSQL 9.1, x64 Debian. Los hice un par de veces para obtener un promedio aproximado. Aquí están los <POINT CONSTRUCTOR METHOD> en orden de la más rápida a la más lenta:

  1. %código%
    • avg 160 ms
    • por mucho más rápido, y conserva la precisión de punto doble (sin pérdida)
    • la forma más sencilla de realizar una consulta parametrizada con datos de coordenadas numéricas
  2. %código%
    • avg 760 ms
    • lento, ya que el número se convierte en texto, luego la cadena se une, luego PostGIS necesita analizarlo para encontrar los números
    • con pérdidas, debido al número - > texto - > conversiones de números
  3. %código%
    • avg 810 ms
    • más lento, no estoy seguro de por qué es más lento que ST_SetSRID(ST_MakePoint(random(), random()), 4326)

Por último, una pequeña nota a pie de página sobre la diferencia entre las conversiones sin pérdida / con pérdida con los métodos anteriores. Solo ST_GeomFromText('POINT(' || random()::text || ' ' || random()::text || ')', 4326) conserva los datos binarios de precisión de punto flotante, y las conversiones de texto truncan una parte muy pequeña de los datos. Aunque los dos puntos pueden tener diferencias binarias (observadas en el WKB), siempre deben ser espacialmente iguales. Las diferencias de distancia son esencialmente la epsilon de la máquina para una doble precisión .

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
    
respondido por el Mike T 20.04.2013 - 12:06
5

ST_MakePoint y ST_Point son iguales: ambos llaman a LWGEOM_makepoint (puedes ver esto en el archivo postgis / postgis.sql.in en el código fuente). Yo usaría ST_MakePoint. Las rutinas de conversión de texto producen el mismo resultado, pero son más lentas debido a la cantidad de análisis que se requiere.

    
respondido por el BradHards 20.04.2013 - 10:24
0

SRID 4326 y Geometría

Como nota al lado de la excelente, completa y actual respuesta de MikeT . Muchas personas parecen hacer esta pregunta porque quieren establecer el SRID en una columna de PUNTOS.

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

Pero cuando lo hacen, tienen problemas con lo que parece ser el mejor método para crear un punto, pero, por desgracia, tienen problemas.

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

Desde allí, tienen dos opciones

  • Establezca el SRID manualmente, ST_SetSRID( ST_MakePoint(1,2) ) , que es la forma más correcta pero es crufty, o
  • Construya a partir de texto usando ST_GeomFromText , esto es lógicamente más lento y no necesita puntos de referencia: PostgreSQL tiene que analizar los argumentos del constructor del texto. También es extremadamente feo en sí mismo.

Por desgracia, hay otra manera.

Tipo de geografía

El SRID predeterminado para geography es 4326. Si eres nuevo, sugeriría usar geography en lugar de geometry . De hecho, en general, si no conoce la diferencia, es probable que desee geography . Puedes cambiar las columnas con bastante facilidad.

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

La inserción ahora es más fácil porque el tipo ya está asociado a SRID 4326 de forma predeterminada. Ahora puede realizar conversiones explícitas a geography , o simplemente dejar que la conversión implícita funcione

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

Que se ve así, (todos insertan la misma cosa)

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 );

Convertir a texto y luego forzar PostgreSQL para analizar el texto con ST_GeomFromText o ST_GeogFromText es tonto y lento.

    
respondido por el Evan Carroll 03.06.2018 - 03:18

Lea otras preguntas en las etiquetas