날짜 표시 줄에서 가장 가까운 지점을 효율적으로 찾는 방법은 무엇입니까?


10

수십만 개의 PostGIS POINT가있는 PostgreSQL 9.1 테이블이 있습니다. 이들 각각에 대해 다른 POINT 테이블에서 가장 가까운 지점을 찾고 싶습니다. 두 번째 표의 점은 전 세계의 격자를 나타내므로 항상 1도 이내에 일치한다는 것을 알고 있습니다. 이것은 지금까지 내가 사용하고있는 쿼리로 GIST 인덱스를 사용하므로 합리적으로 빠릅니다 (총 30 초).

SELECT DISTINCT ON (p.id)
    p.id, ST_AsText(p.pos)
    , ST_AsText(first_value(g.location) OVER (PARTITION BY p.id ORDER BY ST_Distance(p.pos, g.location::geography)))
FROM point p
JOIN grid g ON ST_DWithin(p.pos::geometry, g.location, 1)

유일한 문제는 날짜 표시 줄입니다. 격자 점의 위도는 180이 아니라 -180입니다. ST_Distance의 지오메트리 버전을 사용하는 경우 날짜 줄의 다른쪽에있는 점을 반환하지 않습니다. 예 : p.pos가 POINT(-179.88056 -16.68833)가장 가까운 그리드 포인트 인 POINT(180 -16.25)경우 위의 쿼리는 그것을 반환하지 않습니다. 이 문제를 해결하는 가장 좋은 방법은 무엇입니까?

단일 그리드 포인트 (-180 및 +180)에 대해 두 개의 좌표를 갖고 싶지 않습니다. 이 특정 사례를 확인하는 자체 함수를 추가하려고 시도했지만 더 이상 인덱스를 사용할 수 없기 때문에 쿼리가 5 분 안에 반환되지 않습니다. 또한 ST_DWithin의 지리 버전을 사용해 보았으며 5 분 후에도 해당 쿼리가 반환되지 않았습니다.


좋은 질문입니다 (답변에서 영리하게 해킹하십시오!). 소프트웨어가 경도에 대해 -180 = 180을 인식하지 못하면 아마도 좌표를 추정하는 척하고 가장 가까운 점을 찾기 위해 유클리드 알고리즘을 사용하여 오류를 일으킬 것입니다. 극 근처의 거대한 적도와 + -180 자오선). 이것이 응용 프로그램에서 심각한 문제를 일으키는 지 여부는 잘 모르지만 다른 많은 경우에는 문제가 해결되며 오류를 해결하지 못합니다.
whuber

좋은 점이지만이 경우 클라이언트 응용 프로그램은 다른 "가장 가까운"계산을 수행하지 않습니다. 내 쿼리에서 반환 된 모눈 점과 관련된 일부 데이터 만 가져옵니다.
EM0

답변:


6

좋아, 마침내 날짜 표시 줄 문제를 해결할뿐만 아니라 더 빠른 해킹 방법을 알아 냈습니다.

CREATE OR REPLACE FUNCTION nearest_grid_point(point geography(Point))
RETURNS integer
AS $BODY$
    SELECT pointid
    FROM
    (
            -- The normal case
        SELECT pointid, location
        FROM grid
        WHERE ST_DWithin($1::geometry, location, 1)

        UNION ALL

            -- The dateline hack
        SELECT pointid, location
        FROM grid
        WHERE (ST_X($1::geometry) < -178.75 AND longitude = 180)
    ) sub
    ORDER BY ST_Distance($1, location::geography)
    LIMIT 1;
$BODY$ LANGUAGE SQL STABLE;

SELECT p.id, ST_AsText(p.pos), g.pointid, ST_AsText(g.location)
FROM point p
JOIN grid g ON nearest_grid_point(p.pos) = g.pointid

모든 행에 대해 호출되는이 함수는 원래 창 함수보다 빠르지 만 10 배 이상 빠릅니다. PostgreSQL 성능은 정말 검은 예술입니다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.