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)')
본질적으로 성능의 차이가 있다면 어느 것이 가장 빠릅니까?
답변
내 생각 엔 ST_MakePoint
가장 빠르지 만 100k 랜덤 포인트로 벤치마킹하기에 충분합니다.
\timing
WITH test AS (
SELECT <POINT CONSTRUCTOR METHOD>
FROM generate_series(1,100000)
)
SELECT count(*) FROM test;
그리고 PostgreSQL 9.1, x64 Debian의 PostGIS 2.1 (트렁크) 결과는 다음과 같습니다. 나는 대략적인 평균을 얻기 위해 몇 번이나 했어요. <POINT CONSTRUCTOR METHOD>
가장 빠른 것부터 가장 느린 것까지 순서 는 다음과 같습니다 .
ST_SetSRID(ST_MakePoint(random(), random()), 4326)
- 평균 160ms
- 훨씬 빠른 속도로 더블 포인트 정밀도 유지 (무손실)
- 숫자 좌표 데이터로 매개 변수화 된 쿼리를 작성하는 가장 쉬운 방법
ST_GeomFromText('POINT(' || random()::text || ' ' || random()::text || ')', 4326)
- 평균 760ms
- 숫자가 텍스트로 캐스트되면 문자열이 함께 조각화되고 PostGIS는 숫자를 찾기 위해 구문 분석해야합니다.
- 숫자-> 텍스트-> 숫자 변환으로 인해 손실
ST_GeomFromEWKT('SRID=4326;POINT(' || random()::text || ' ' || random()::text || ')')
- 평균 810ms
- 가장 느리다. 왜 느리다.
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
답변
ST_MakePoint와 ST_Point는 동일합니다. 둘 다 LWGEOM_makepoint를 호출합니다 (소스 코드의 postgis / postgis.sql.in 파일에서 확인할 수 있음). ST_MakePoint를 사용합니다. 텍스트 변환 루틴은 동일한 결과를 생성하지만 필요한 구문 분석 양으로 인해 속도가 느려집니다.
답변
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은 텍스트에서 생성자의 인수를 구문 분석해야합니다. 또한 그 자체가 매우 추악합니다.
아아, 다른 방법이 있습니다.
지리 유형
의 기본 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
이것은 다음과 같습니다 (모두 같은 것을 삽입합니다)
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
느리게합니다.