OpenStreetMap PostGIS 쿼리 속도 향상


12

osmosis 스키마를 사용하여 네덜란드의 OpenStreetMap 데이터를 PostGIS 데이터베이스 (PostgreSQL 8.3 / PostGIS 1.3.3)에로드했습니다 . 이는 모든 태그가 hstore 필드에 저장됨을 의미 합니다. 삼투가 지오메트리 필드에 생성하는 GIST 인덱스 외에도 tags 필드에 추가 GIST 인덱스를 만들었습니다.

태그 필드에서 공간 제약 조건과 제약 조건을 모두 사용하여 쿼리하려고하면 원하는 것보다 느립니다. 이와 같은 쿼리 :

SELECT n.geom,n.tags,n.tstamp,u.name FROM nodes AS n 
  INNER JOIN users AS u ON n.user_id = u.id 
  WHERE tags->'man_made'='surveillance' 
  AND ST_Within(geom, ST_GeomFromText('POLYGON((4.0 52.0,5.0 52.0,5.0 53.0,4.0 53.0,4.0 52.0))',4326));

78 개의 레코드를 반환하는 데 22 초가 걸립니다.

이 표에는 약 5 천 5 백만 개의 레코드가 있습니다.

이 속도를 크게 높일 수있는 방법이 있습니까? PostgreSQL 9에서 hstore가 크게 향상되었다고 들었습니다. 도움이 될까요?


이것은 데이터베이스 중심의 질문으로 보이므로 dba.stackexchange.com
jcolebrand

2015 년 업데이트-PostGIS는이 질문이 제기 된 이후 성능이 크게 향상되었으므로 PostgreSQL 업그레이드뿐만 아니라이를 고려하십시오.
Toby Speight

답변:


5

한 가지 방법은 관심있는 태그를 쿼리하고 해당 레코드를 새 테이블에 배치하는 것입니다. 그런 다음 5,500 만 개의 레코드 대신 새 테이블 만 쿼리하면됩니다. 데이터베이스를 최신 상태로 유지하려는 경우 OSM에서 새 데이터를 얻을 때마다이 쿼리를 실행할 수 있습니다.


2
새 테이블을 생성하는 대신 VIEW를 생성하는 대신 데이터를 문자 그대로 복제하지 않고도 원본 데이터에 "쿼리"할 수 있습니다.
RyanKDalton

7
구체화 된 뷰이거나 이와 동등한 뷰가 아닌 한 뷰가 쿼리 성능을 반드시 향상 시키지는 않습니다 ( 이 주제에 대한 SO 질문 참조 ). Postgresql은 구체화 된 뷰를 직접 지원한다고 생각하지 않지만 트리거를 사용하여 구현할 수 있습니다.
Adam Armor

2
이것이 현재 사용중인 해결 방법입니다. osmosis 테이블을 업데이트 한 후 실행하려는 쿼리에 최적화 된 몇 가지 테이블을 다시 만듭니다. 나는 더 좋은 방법이 있어야한다고 생각합니다. 방아쇠에 관한 주제는 저에게 흥미롭고 그것들을 사용하여 머티리얼 뷰를 구현하는 방법에 관한 것입니다. @Adam Armour, 이것에 대한 통찰력을 공유 할 수 있습니까?
mvexel

4
@mvexel 구체화 된 뷰의 기본 사항과 PostgreSQL에서이를 구현하는 방법을 자세히 설명하는 이 위키 기사를 살펴보십시오 .
Adam Armor

5

hstore 열에 대한 색인을 만들 수 있습니다.

CREATE INDEX nodes_tags_idx ON nodes USING GIST(tags)

그런 다음 ?연산자를 사용하여 쿼리를 해당 행으로 만 제한하십시오.

SELECT n.geom,n.tags,n.tstamp,u.name FROM nodes AS n 
  INNER JOIN users AS u ON n.user_id = u.id 
  WHERE tags ? 'man_made'
  AND tags->'man_made'='surveillance' 
  AND ST_Within(geom, ST_GeomFromText('POLYGON((4.0 52.0,5.0 52.0,5.0 53.0,4.0 53.0,4.0 52.0))',4326));

감사! 나는 이미 그 색인을 만들었지 만 사용하지 않았다. 특정 작업 속도 만 향상시킵니다. PostgreSQL 8.3 (사용중인)은 @> 및? , 9.0에서는 @>,?,? & 및? | .
mvexel

1
기록을 위해 ?연산자를 사용하는 쿼리는 쿼리의 88 초와 비교하여 48 초가 걸렸습니다 (어제 72 초를 어떻게 얻었는지 모르겠습니다. 이번에는 쿼리를 수행하는 동안 컴퓨터가 복잡한 작업을 수행했을 수 있습니다). 여전히 찾고있는 성능은 아니지만 hist 열에서 GIST 색인이 작동하는 방식에 대해 더 깊이 이해했습니다. 원하는 성능을 얻으려면 구체화 된 뷰를 만드는 다른 솔루션을 사용해야합니다.
mvexel

3

st_within 및 _st_within 함수는 해당 속도로 알려져 있지 않습니다. && 연산자는 지오메트리 대신 bbox를 검사하므로 도움이 될 수 있습니다.

다음을 시도해보십시오.

SELECT n.geom,n.tags,n.tstamp,u.name FROM nodes AS n 
  INNER JOIN users AS u ON n.user_id = u.id 
  WHERE tags ? 'man_made'
  AND tags->'man_made'='surveillance' 
  AND geom && ST_SetSRID('BOX3D(4 52,5 53)'::box3d,4326);

더 많은 성능 팁을 확인하려면 다음을 확인하십시오 : http://postgis.refractions.net/docs/ch06.html


2

쿼리의 문제는 tags->'man_made'='surveillance'절입니다. 이로 인해 Postgres는 hstore 태그를 확장하고 인덱스를 사용할 수 없습니다. @>(포함)을 사용하여 이것을 다시 쓰면 인덱스 사용이 허용됩니다.

사각형을 쿼리하기 때문에 &&ST_Within 대신 사용할 수 있습니다 . ST_Within은 평가하기가 복잡하지 않으며 ST_Within은 암시 적으로 &&검사를 수행하므로 약간의 이득이 있습니다.

추가적인 속도 증가는 GIST 인덱스 대신 태그에 GIN 인덱스를 사용하는 것입니다. GIN 인덱스는 빌드하는 데 시간이 오래 걸리지 만 더 빠릅니다.

전체 쿼리는

SELECT n.geom,n.tags,n.tstamp,u.name FROM nodes AS n INNER JOIN users AS u ON n.user_id = u.id WHERE tags @> hstore('man_made', 'surveillance') AND geom && ST_GeomFromText('POLYGON((4.0 52.0,5.0 52.0,5.0 53.0,4.0 53.0,4.0 52.0))',4326);

특정 태그를 많이 쿼리한다는 것을 알고 있다면로 태그를 생성 할 수 있습니다 CREATE INDEX ON nodes ( tags->'man_made' ) WHERE (tags->'man_made' IS NOT NULL);.

이렇게하면 WHERE 조건 tags->'man_made'='surveillance'이 인덱스를 사용할 수 있습니다. 불행하게도,이 인덱스는 @>쿼리를 도울 수 없으며 GIN 또는 GIST 인덱스는 tags->'foo'쿼리를 도울 수 없으므로 쿼리를 가지고있는 인덱스와 일치시켜야합니다.


tags @>hstore()덕분에 쿼리를 크게 개선 하라는 조언을 받았습니다.
alphabetasoup

1

대신 이것을 시도하십시오 :

n.geom, n.tags, n.tstamp, u.name 노드에서 이름을 선택하십시오. , ST_GeomFromText ( 'POLYGON ((4.0 52.0,5.0 52.0,5.0 53.0,4.0 53.0,4.0 52.0))', 4326));

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