GIST 인덱스 (<-> 기능)를 사용하는 Postgis 2.0에서 가장 가까운 이웃 문제


25

Postgis 2.0 새로운 함수 <-> (Geometry Distance Centroid)를 사용하여 테이블의 각 행 (cosn1)에 대해 동일한 클래스의 가장 가까운 다각형까지의 거리를 계산하려고합니다.

다음 코드를 사용하려고했습니다.

WITH index_query AS (
  SELECT g1.gid As ref_gid, ST_Distance(g1.the_geom,g2.the_geom) As ENN    
    FROM "cosn1" As g1, "cosn1" As g2   
    WHERE g1.gid <> g2.gid AND g1.class = g2.class
    ORDER BY g1.gid, g1.the_geom <-> g2.the_geom) 
SELECT DISTINCT ON (ref_gid) ref_gid, ENN 
    FROM index_query
ORDER BY ref_gid, ENN;

그러나 나는 경고를 깨달았다.

참고 : 지오메트리 중 하나가 상수 (하위 쿼리 / cte가 아닌) 인 경우에만 인덱스가 시작됩니다. 예 : a.geom 대신 'SRID = 3005; POINT (1011102 450541)':: geometry

인덱스가 전혀 사용되지 않으며 쿼리를 사용하기 전과 거의 동일한 시간이 소요됩니다.

SELECT DISTINCT ON(g1.gid)  g1.gid As ref_gid, ST_Distance(g1.the_geom,g2.the_geom) As ENN    
    FROM "cosn1" As g1, "cosn1" As g2   
    WHERE g1.gid <> g2.gid AND g1.class = g2.class
    ORDER BY g1.gid, ST_Distance(g1.the_geom,g2.the_geom)

누구든지 내 쿼리 성능을 향상시킬 수있는 해결 방법을 알려 줄 수 있습니까?

대단히 감사합니다.


아직 응답이 없으면 PostGIS 메일 링리스트에서 질문 할 수 있습니다.
GIS-Jonathan

나는 이미했지만 아무런 반응도 없었다.
Alexandre Neto

3
where 절에서 g1.gid> g2.gid를 사용하면 거리 계산 횟수를 줄일 수 있습니다. 불행히도 <-> 연산자가 상수없이 작동 할 때까지 이런 종류의 쿼리에서는 속도가 크게 향상되지 않습니다.
John Powell

존, 나는 "cosn1"테이블에있는 다각형들 각각에 대해 EEN을 업데이트해야 할 때 반복되는 것들까지 모든 GI를 유지해야합니다. 그러나 당신이 말한 것은 나에게 아이디어를 주었다. g1.gid> g2.gis를 사용하여 거리 계산을 줄이면서 g1.gid 및 g2.gid를 결과에 유지하면 말할 수 있습니다. 그 후 두 개의 하위 쿼리를 통합 할 수 있습니다 (하나는 g1.gis로 gid, 다른 하나는 g2.gid로). 감사합니다
Alexandre Neto

상수 문제를 해결할 수있는 해결책은 the_geom을 매개 변수로 사용하여 SQL 함수 내부에서 <->를 사용하는 것입니다. 나는 몇 가지 테스트를했으며 어떤 경우에는 훨씬 빠릅니다 (). 그러나 필자의 경우 거리가 동일한 테이블 내에 있기 때문에 프로세스 중에 많은 거리 계산이 반복되어 직접 쿼리를 사용하는 것보다 느립니다.
Alexandre Neto

답변:


2

이 연산자 <->가 제대로 작동하지 않는 것처럼 들리는 내 컴퓨터에서 일부 테스트를 수행하는 험. 나는 그것이 버그인지 확실하지 않지만 겹치지 않는 기하학에서 거리가 0이라고보고했다. 안돼?

기존의 전통적인 SQL 쿼리 최적화는 어떻습니까? <-> 연산자로 예기치 않은 결과가 발생하므로 st_centroid로 바꿉니다. 속도면에서 훨씬 더 나은 결과를 얻었습니다.

st_overlaps를 가진 희망 의미가 동일하게 유지됩니다. 적어도 이것은 <->에 대한 문서에서 이해했습니다.

Postigs의 문서에서 <->

다른 형상 유형의 경우 부동 소수점 경계 상자 중심 사이의 거리가 반환됩니다.

~ 5.5k 폴리곤을 사용한 테스트 데이터에서 공간 인덱싱없이 ~ 1000 초에서 ~ 5 초의 속도가 향상되었습니다.

어쨌든 DISTINCT ON을 사용하여 그룹화하는 이유는 무엇입니까? 중복을 제거하기 위해 그룹을 사용하지 않는 사람들이 있습니까?

st_centroid 오류없이 표준 SQL 최적화를 사용하는 쿼리

select g1.gid, min( st_distance( g1.the_geom, g2.the_geom ) ) AS enn
FROM 
  "cosn1" AS g1, "cosn1" AS g2
WHERE
  g1.gid <> g2.gid
  AND g1.class = g2.class
  AND g1.the_geom && g2.the_geom
GROUP BY
  g1.gid

행복한 크리스마스 휴가!


죄송하지만 귀하의 답변으로 문제가 해결되지 않습니다. 실제로는 훨씬 빠르지 만 최종 결과는 실제 지오메트리 대신 다각형의 중심을 사용하여 계산되므로 결과가 정확하지 않습니다. <->는 가장 가까운 이웃에 대한 후보자 검색을 최적화하는 것을 목표로하지만 결국 실제 지오메트리를 사용하여 최상의 후보자까지의 거리를 계산해야합니다. 또한 DISTINCT ON \ ORDER BY 대신 MIN \ GROUP BY를 사용해 보았는데 속도가 느린 것 같습니다.
Alexandre Neto

그러나 연산자 <->에 대한 postgis 매뉴얼은 비점 기하학에 중심을 사용한다고 명시하고 있습니다. 그래서 내 솔루션은 비슷한 결과를 줄 것입니다. 인기 검색어와 동일한 결과를 제공해야합니다. <-> 연산자의 결과도 올바른지 확인하십시오. 테스트 데이터에서 길이가 0 인 기하학을보고하여 결과가 깨질 수 있으며이 솔루션은보다 정확한 데이터를 제공했습니다. 일부 Pastie 사이트에서 오류를 보여주는 샘플 레코드를 게시 할 수 있다면 솔루션의 결함을 발견 할 수 있습니다.
cavila

내 쿼리를 확인하면 <-> 연산자는 후보를 주문하는 데만 사용되며 최종 결과는 실제 지오메트리를 사용하여 계산됩니다. 어쨌든, 앞에서 말했듯이 <-> 성능 향상은 고정 소수점에서만 작동합니다. 그게 내 원래의 질문이었습니다.
Alexandre Neto

따라서 최상위 쿼리가 하위 쿼리와 동일하지 않다는 데 동의하십니까? <-> 연산자가 ORDER BY st_centroid와 st_distance가 다른 값을 제공하기 때문에 순서가 변경되므로? 순서가 다르면 DISTINCT ON 절을 전달할 첫 번째 행과 다른 쿼리를 가져올 수 있습니까? 유효한 쿼리는 속도 향상이 필요한 가장 낮은 쿼리입니까?
cavila

예, 첫 번째 쿼리는 맨 아래 쿼리의 속도를 향상시키기위한 것입니다. 그리고 예, g1.geom <-> g2.geom은 중심을 사용하기 때문에 약간 다른 결과를 줄 수 있으며, 이는 첫 번째 행이 더 가깝지 않을 수 있음을 의미합니다. 그것이 작동하게하려면 order by 조항에 limit 10을 말한 다음 거리의 실제 값을 추출해야한다고 생각합니다. 대신 중심 대신 경계 상자를 사용하는 <#>을 사용할 수도 있습니다.
Alexandre Neto
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.