PostgreSQL 실시간 위치 추적 + 궤적 분석 시스템 실천 - 단기 천억 궤적/일

12843 단어

라벨


PostgreSQL, PostGIS, 동적 업데이트 위치, 트랙 추적, 공간 분석, 시공 분석

배경.


모바일 기기가 보급됨에 따라 점점 더 많은 업무가 시공 속성을 갖추었다. 예를 들어 택배는 소포, 택배원의 위치를 추적해 본다.예를 들어 실체는 공간 속성을 갖추고 있다.
예를 들어 음식 배달, 배달원 위치 속성.예를 들어 차량, 실시간 위치.잠깐만요.
두 가지 주요 요구 사항은 다음과 같습니다.
1. 대상의 위치를 실시간으로 추적한다. 예를 들어 특정한 위치 근처나 다각형 구역 내의 배달원을 실시간으로 조회한다.
2. 대상 위치 궤적 기록과 분석.지도와 결합하여 궤적을 분석하고 루트 알고리즘을 결합시켜 최적 경로를 예측하고 생성한다.

DEMO


택배 배송의 경우 GPS 장비가 택배기사의 궤적을 실시간으로 보고하고 위치 추적 시스템에 기록하는 동시에 궤적 기록을 궤적 분석 시스템에 영구적으로 저장한다.
택배기사가 배송 과정에서 오래 머무를 수 있기 때문에 (예를 들어 어느 동네에서 배송할 때) 보고된 여러 위치의 변화가 크지 않을 수 있다. 또한 데이터베이스 업데이트 소모와 위치의 시효성을 고려하면 일부 점의 업데이트를 피할 수 있다(예를 들어 지난번 위치와 현재 위치의 변화량이 50미터일 때 업데이트하지 않는다).
동적 업데이트는 데이터베이스의 업데이트량을 줄이고 전체적인 삼키기 능력을 향상시킬 수 있다.

설계


실시간 위치 업데이트


1. 표 작성
create table t_pos (  
  uid int primary key,   --  、 、 、。。。 ID  
  pos point,             --    
  mod_time timestamp     --    
);  
  
create index idx_t_pos_1 on t_pos using gist (pos);  

실제 환경에서 우리는 PostGIS 공간 데이터베이스 플러그인을 사용하고geometry 데이터 형식을 사용하여 경위도점을 저장할 수 있다.
create extension postgis;  
  
create table t_pos (  
  uid int primary key,   --  、 、 、。。。 ID  
  pos geometry,          --    
  mod_time timestamp     --    
);  
  
create index idx_t_pos_1 on t_pos using gist (pos);  

2. 에스컬레이션 위치는 자동으로 이동 범위에 따라 위치를 업데이트한다.
예를 들어 이동 거리가 50미터 이내이면 갱신하지 않는다.
insert into t_pos values (?, st_setsrid(st_makepoint($lat, $lon), 4326), now())  
on conflict (uid)  
do update set pos=excluded.pos, mod_time=excluded.mod_time  
where st_distancespheroid(t_pos.pos, excluded.pos, 'SPHEROID["WGS84",6378137,298.257223563]') > ?;  --    

역사 궤적 저장


일반적으로 단말기는 10초 간격으로 10초 간격으로 채집한 점을 대량으로 보고한다. 한 번에 보고된 데이터는 여러 개의 점을 포함할 수 있으며PostgreSQL에 수조로 저장할 수 있다.
create table t_pos_hist (  
  uid int,                  --  、 、 、。。。 ID  
  pos point[],              --    
  crt_time timestamp[]      --    
);   
  
create index idx_t_pos_hist_uid on t_pos_hist (uid);                 --  ID  
create index idx_t_pos_hist_crt_time on t_pos_hist ((crt_time[1]));    --    

필요하면 섹션에 사용할 시간 필드를 하나 더 저장할 수 있습니다.

역사적 궤적 분석


동적 위치 변경 압력 측정


쓰기 및 병합, 그리고 거리가 50보다 크면 업데이트되지 않고 그렇지 않으면 업데이트되지 않음을 판단합니다.
(테스트)point 유형을 사용하면 다음과 같은 SQL을 사용합니다
insert into t_pos values (1, point(1,1), now())  
on conflict (uid)  
do update set pos=excluded.pos, mod_time=excluded.mod_time  
where t_pos.pos  excluded.pos > 50;  

(실제 생산) PostGIS의geometry 유형을 사용하면 다음과 같은 SQL을 사용합니다
insert into t_pos values (1, st_setsrid(st_makepoint(120, 71), 4326), now())  
on conflict (uid)  
do update set pos=excluded.pos, mod_time=excluded.mod_time  
where st_distancespheroid(t_pos.pos, excluded.pos, 'SPHEROID["WGS84",6378137,298.257223563]') > 50;  

압력 측정


우선 1억 랜덤 공간 대상 데이터를 생성한다.
postgres=# insert into t_pos select generate_series(1,100000000), point(random()*10000, random()*10000), now();  
INSERT 0 100000000  
Time: 250039.193 ms (04:10.039)  

스크립트는 다음과 같습니다. 1억 공간 대상, 동적 업데이트 성능(50 이내, 갱신하지 않음)을 테스트합니다.
vi test.sql    
  
\set uid random(1,100000000)    
insert into t_pos    
select uid, point(pos[0]+random()*100-50, pos[1]+random()*100-50), now() from t_pos where uid=:uid   
on conflict (uid)   
do update set pos=excluded.pos, mod_time=excluded.mod_time   
where t_pos.pos  excluded.pos > 50;   

압력 측정 결과, 동적 갱신 21.6만 점/s, 187억 점/일.
pgbench -M prepared -n -r -P 1 -f ./test.sql -c 64 -j 64 -T 120   
  
number of transactions actually processed: 26014936
latency average = 0.295 ms
latency stddev = 0.163 ms
tps = 216767.645838 (including connections establishing)
tps = 216786.403543 (excluding connections establishing)

궤적 쓰기 압력 측정


각 UID, 배치 당 50 개 쓰기: 쓰기 속도는 약 467.5만 포인트/s, 4039억 포인트/일.
압력 측정을 할 때, 여러 표를 쓰고, 압력 측정은 동적 SQL을 사용한다.
do language plpgsql $$  
declare  
begin  
  for i in 0..127 loop  
    execute 'create table t_pos_hist'||i||' (like t_pos_hist including all)';  
  end loop;  
end;  
$$;  
create or replace function import_test(int) returns void as $$  
declare  
begin  
  execute format('insert into t_pos_hist%s values (%s, %L, %L)', mod($1, 128), $1,   
  array[point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1)] ,  
  array['2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10']);  
end;  
$$ language plpgsql strict;  
vi test1.sql  
  
\set uid random(1,100000000)  
select import_test(:uid);  
pgbench -M prepared -n -r -P 1 -f ./test1.sql -c 56 -j 56 -T 120   
  
  
number of transactions actually processed: 11220725  
latency average = 0.599 ms  
latency stddev = 5.452 ms  
tps = 93504.532256 (including connections establishing)  
tps = 93512.274135 (excluding connections establishing)  

흑과학 기술


1. 블록급 인덱스(BRIN)는 시퀀스 속성 필드에 블록급 인덱스를 구축하면 효율적인 검색 목적을 달성할 수 있을 뿐만 아니라 인덱스 공간도 절약할 수 있고 쓰기도 가속화할 수 있다.
PostgreSQL BRIN 인덱스의 페이지s per range 옵션 최적화와 커널 코드 최적화에 대한 생각
《만억급 전자상거래 광고-brin 블랙 테크놀로지(최저 원가) 밀리초급 권자(시각 발굴 자매편) - 아리운 RDS PostgreSQL, HybridDB for PostgreSQL 최적 실천》
《PostGIS 공간 인덱스(Gist, BRIN, R-Tree) 선택, 최적화 - 아리운 RDS PostgreSQL 최적 실천》
올바른 인덱스 접근 인터페이스 (btree,hash,gin,gist,sp-gist,brin,bitmap...) 를 자동으로 선택합니다.방법
《PostgreSQL 병렬 쓰기 더미표, 시차적 선형 저장 - BRIN 인덱스 최적화를 어떻게 보장합니까》
PostgreSQL 9가지 인덱스의 원리와 응용 장면
2, 아리운 HDB PG 특성:sort key, metascan
BRIN과 유사하게 선형 데이터에 적합하며 블록 레벨 메타데이터(수치범위, 평균값, CNT, SUM 등)를 자동으로 만들어 필터링합니다.
3. 공간 색인
Gist, SP-Gist 공간 인덱스, 공간 데이터 및 기타 이기종 데이터에 적합합니다.
4. 동적 통합 쓰기, 위치 변화량에 따라 통합 업데이트가 필요한지 자동으로 판단합니다.
insert on conflict 문법, Do 업데이트에서 조건 필터를 할 수 있으며, 위치 변화가 N미터를 초과할 때 업데이트됩니다.
5, 배열, JSON, KV 등 여러 값 유형.
특히 다수치 속성에 적합하다. 예를 들어 대량 업로드의 궤적은 보통 GPS 단말기의 보고 위치가 실시간이 아니기 때문에 일정한 지연(예를 들어 대량 보고)이 있을 수 있다.배열, JSON을 사용하여 저장할 수 있습니다.
만약 그룹 저장소를 사용한다면, 장래에 궤적을 분석할 때, 여전히 unnest에서 풀고 궤적을 그릴 수 있습니다.

성능


1. 동적 위치 변경: 1억 추적 대상, TPS:21.6만 명, 동적 업데이트 21.6만 점/s, 187억 점/일.
2. 궤적 기록: tps 약 10만, 467.5만 점/s, 4039억 점/일.

참고 자료


PostGIS 공간 데이터 학습 제안
PostgreSQL+PostGIS+SFCGAL 우아한 3D 데이터 처리
PostGIS 거리 계산 제안 - 투영과 구 좌표계,geometry와geography 유형
PostgreSQL 10 + PostGIS + Sharding (pg pathman) + MySQL (fdw 외부 테이블) on ECS 배치 가이드 (새 사용자에게 적합)
《PostGIS 공간 인덱스(Gist, BRIN, R-Tree) 선택, 최적화 - 아리운 RDS PostgreSQL 최적 실천》
PostGIS 좌표 변환(SRID)의 경계 문제로 인한 전문 지식 - ST Transform)
《무인 운전 배후의 기술 - PostGIS 점운(pointcloud) 응용 - 2》
《무인 운전 배후의 기술 - PostGIS 점운(pointcloud) 응용 - 1》
《geohash vs PostGIS》
'비주얼 발굴과 PostGIS 공간 데이터베이스의 완벽한 만남-광고 마케팅\권인'
PostGIS 점면 중첩 시각적 판단 출력
PostGIS 다중 형상 유형 빈 문자 구조 예외 CASE
《오픈맵 OpenStreetMap과 PostGIS의 삼생삼세십리도화》
PostGIS 지리적 정보, 그리드 데이터 다중 핵 병렬 처리(st memunion, st union))
《벌집의 예술과 기술적 가치 - PostgreSQL PostGIS's hex-grid》
《GIS 테스트 환경을 구축하는 방법 - Openstreetmap의 샘플 데이터를 PostgreSQL PostGIS 라이브러리로 가져오기》
<GIS 부근 검색 성능 최적화 - PostGIS long lat geometry distance search tuning using gist knn function>

좋은 웹페이지 즐겨찾기