Яка функція створення POINT у PostGIS?


30

Визначаючи точку в 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
Еван Керролл

Відповіді:


26

Я здогадуюсь, що ST_MakePointце найшвидше, але це досить просто для порівняння зі 100 000 випадкових балів.

\timing

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

Ось кілька результатів із PostGIS 2.1 (магістраль) на PostgreSQL 9.1, x64 Debian. Я робив їх кілька разів, щоб отримати приблизну середню. Ось <POINT CONSTRUCTOR METHOD>порядок від найшвидшого до найповільнішого:

  1. ST_SetSRID(ST_MakePoint(random(), random()), 4326)
    • сер. 160 мс
    • набагато швидше і зберігає подвійну точність (без втрат)
    • найпростіший спосіб зробити параметризований запит з числовими даними координат
  2. ST_GeomFromText('POINT(' || random()::text || ' ' || random()::text || ')', 4326)
    • сер 760 мс
    • повільно, оскільки число передається в текст, то рядок розділяється разом, то PostGIS потрібно розібрати його, щоб знайти числа
    • втрата, через число -> текст -> число перетворень
  3. ST_GeomFromEWKT('SRID=4326;POINT(' || random()::text || ' ' || random()::text || ')')
    • сер 810 мс
    • повільніше, не впевнений, чому це повільніше, ніж ST_GeomFromText

Нарешті, примітка про різницю між конверсіями без втрат / втрат у вищезазначених методах. Лише ST_MakePointзберігаються дані про точність двійкової плаваючої точки, а текстові перетворення урізають дуже незначну частину даних. Хоча обидві точки можуть мати бінарні відмінності (видно у WKB), вони завжди повинні бути просторово рівними. Перепади відстаней по суті є машинним епсилоном для подвійної точності .

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

1
Дякую за чудове пояснення, як це обчислити. Я цікавий про SQLсинтаксисі <POINT CONSTRUCTOR METHOD>. Це просто псевдокод для позначення чотирьох різних підходів, або ви робите якусь функцію?
djq

2
@djq yup, це просто заповнення фактичного коду SQL в 1, 2 та 3.
Майк Т

Детально про обмеження точності на типі даних поплавця для використання в якості посилання ... Епсилон машини - це 1e-14... ... Змініть таблицю f1, FROM (SELECT random()::float8 as x, random()::float8 as y UNION SELECT 12.24343484842,34.58384538483434) AS f1щоб побачити її у вашому psql.
Пітер Краусс

5

ST_MakePoint і ST_Point однакові - вони обидва викликають LWGEOM_makepoint (це можна побачити у файлі postgis / postgis.sql.in у вихідному коді). Я б використовував ST_MakePoint. Підпрограми перетворення тексту дають той самий результат, але повільніше через необхідну кількість аналізу.


1

SRID 4326 та Геометрія

Як сторону відзначають відмінну, вичерпну та актуальну відповідь від MikeT . Багато людей, здається, задають це питання, тому що хочуть встановити SRID на стовпчик POINT.

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 повинен аналізувати аргументи конструктора з тексту. Це теж само по собі надзвичайно потворно.

На жаль, є інший шлях.

Тип географії

За замовчуванням SRID geography- 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

Як виглядає так, (всі вони вставляють hte одне і те ж)

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

Перетворення в текст, а потім змушення PostgreSQL для розбору тексту з ST_GeomFromTextабо ST_GeogFromTextбезглуздо і повільно.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.