PostgreSQL - 지리적 위치 쿼리를 강화하는 방법
우선 data.gouv.fr 웹 사이트에서 데이터 세트를 검색했습니다. https://www.data.gouv.fr/fr/datasets/liste-des-boites-aux-lettres-de-rue-france-metropolitaine-et-dom-avec-heure-limite-de-depot-1/ . 이 데이터 세트에는 140,000개의 항목이 포함되어 있습니다. 물론 그와 가까운 사서함을 표시하려는 사용자는 데이터베이스에서 사용 가능한 모든 사서함을 표시할 필요가 없고 예를 들어 10km와 같이 그와 가까운 사서함만 표시할 필요가 있습니다.
내 프로젝트에서는 SpringBoot API를 사용하지만 오늘 관심을 가질 내용은 아닙니다. 실제 문제는 PostgreSQL 데이터베이스에 저장된 모든 데이터를 검색하는 방법입니다. 이 데이터는 편리한 시간에 가까운 지점에 위치합니다!
목표
내 목표는 기록적인 시간 내에 반경 10km 내에 있는 일련의 지점을 찾는 것입니다!
구조에 PostGIS
PostGIS는 PostgreSQL의 확장으로 지리적 위치 검색을 용이하게 하는 새로운 기능과 데이터 유형을 제공합니다.
서버에 PostGIS를 설치하려면:
~$ sudo apt install postgis
그런 다음 데이터베이스에 연결하고 postgis 확장을 추가하여 PosgresSQL에서 활성화해야 합니다. 그러면 선택한 데이터베이스에서만 활성화됩니다.
psql (13.6 (Ubuntu 13.6-0ubuntu0.21.10.1))
Type "help" for help.
postgres=# \c test;
postgres=# CREATE EXTENSION postgis;
이제 ID, 위도, 경도 및 GPS 지점을 포함하는 테이블을 만들 수 있습니다. SRID 4326 값은 지리적 참조 시스템을 사용하는 지점을 선언하는 데 사용됩니다.
CREATE TABLE public.test (
id bigserial NOT NULL,
lat real NOT NULL,
long real NOT NULL,
location geography(Point, 4326) NOT NULL
);
그런 다음 다음 쿼리를 사용하여 포인트를 쉽게 추가할 수 있습니다.
INSERT INTO test (lat, long, location)
VALUES (49.548462,1.0779799,ST_SetSRID(ST_MakePoint(49.548462,1.0779799), 4326));
최적화
최적화를 검증하기 위해 140,000행의 위치 정보 데이터를 테이블에 추가했습니다.
어리석게도 st_distancesphere 함수로 반경 10km 이내의 모든 지점을 검색하고 싶었습니다.
다음은 반경 10km 내의 모든 GPS 지점을 검색하기 위해 실행하는 쿼리입니다.
EXPLAIN(ANALYSE , BUFFERS )
SELECT st_distancesphere(t.location::geometry,ST_SetSRID(ST_MakePoint(49.548462,1.0779799), 4326))
FROM test t
WHERE
st_distancesphere(t.location::geometry,ST_SetSRID(ST_MakePoint(49.548462,1.0779799), 4326)) < 10000;
PostgeSQL 쿼리 분석은 인덱스가 사용되지 않았으며 쿼리가 조건과 일치하는 21개의 포인트를 반환하는 데 463ms가 걸린다는 것을 보여줍니다.
Gather (cost=1000.00..2776968.00 rows=47062 width=8) (actual time=160.851..461.391 rows=115 loops=1)
Workers Planned: 1
Workers Launched: 1
Buffers: shared hit=1759
-> Parallel Seq Scan on test t (cost=0.00..2771261.80 rows=27684 width=8) (actual time=218.887..415.046 rows=58 loops=2)
" Filter: (st_distance(geography((location)::geometry), '0101000020E6100000A48CB80034C64840F5EC03DA673FF13F'::geography, false) < '10000'::double precision)"
Rows Removed by Filter: 70535
Buffers: shared hit=1759
Planning Time: 0.376 ms
JIT:
Functions: 8
" Options: Inlining true, Optimization true, Expressions true, Deforming true"
" Timing: Generation 2.485 ms, Inlining 178.841 ms, Optimization 117.797 ms, Emission 56.983 ms, Total 356.106 ms"
Execution Time: 463.431 ms
따라서 쿼리 속도를 높일 수 있는 인덱스를 만들 것입니다(http://postgis.net/workshops/postgis-intro/indexing.html 참조).
CREATE INDEX test_position_geography_index ON test USING GIST(geography(location));
그러나 색인이 여전히 작동하지 않기 때문에 우리는 불쾌한 놀라움에 처해 있습니다. 빠른 검색 후 특정 PostGIS 기능만 인덱싱을 사용할 수 있다는 것을 알았습니다(여기 문서 참조: http://postgis.net/workshops/postgis-intro/indexing.html#spatially-indexed-functions ).
그래서 두 점이 세 번째 매개변수에 지정된 거리에 있으면 true를 반환하는 ST_DWithin 함수를 사용하기로 했습니다.
다음은 분석에 따른 쿼리입니다.
EXPLAIN(ANALYSE , BUFFERS )
SELECT st_distancesphere(t.location::geometry,ST_SetSRID(ST_MakePoint(49.548462,1.0779799), 4326))
FROM test t
WHERE
ST_DWithin(t.location, ST_SetSRID(ST_MakePoint(49.548462,1.0779799), 4326)::geography, 10000);
Bitmap Heap Scan on test t (cost=4.95..2390.34 rows=14 width=8) (actual time=1.212..2.205 rows=115 loops=1)
" Filter: st_dwithin(location, '0101000020E6100000A48CB80034C64840F5EC03DA673FF13F'::geography, '10000'::double precision, true)"
Rows Removed by Filter: 200
Heap Blocks: exact=150
Buffers: shared hit=188
-> Bitmap Index Scan on test_position_geography_index (cost=0.00..4.95 rows=72 width=0) (actual time=0.288..0.288 rows=315 loops=1)
" Index Cond: (location && _st_expand('0101000020E6100000A48CB80034C64840F5EC03DA673FF13F'::geography, '10000'::double precision))"
Buffers: shared hit=26
Planning Time: 0.446 ms
Execution Time: 2.288 ms
test_position_geography_index가 사용되고 2.288ms 🤯에서 21포인트를 복구할 수 있음을 알 수 있습니다. 이득은 엄청나며 실행 시간과 프로세서 사용 시간을 상당히 줄일 수 있습니다.
내 편지함 지리 위치 API에서 이를 통해 Apache ab 성능 테스트 도구( https://httpd.apache.org/docs/2.4/fr/programs/ab.html )로 서버 로드를 시뮬레이션할 때 요청 시간을 10분의 1로 단축하고 서버 부하를 완화할 수 있었습니다.
PostGIS와 함께 즐거운 시간 보내세요. 훌륭한 도구입니다 ;)
Reference
이 문제에 관하여(PostgreSQL - 지리적 위치 쿼리를 강화하는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/giboow/postgresql-how-to-boost-your-geolocation-point-searches-fn3텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)