背景 之前做的海量數據數據展示,在預處理速度和線上渲染上還有有所欠缺,本文中進行一些優化工作,使得九分鐘處理完一千多萬面數據的3 12級矢量切片,線上瀏覽數據請求時間控制在10s左右。 準備 軟體環境:PostGIS(3.0.0rc2 r17909)和 PostgreSQL( 12.0, compi ...
背景
之前做的海量數據數據展示,在預處理速度和線上渲染上還有有所欠缺,本文中進行一些優化工作,使得九分鐘處理完一千多萬面數據的3-12級矢量切片,線上瀏覽數據請求時間控制在10s左右。
準備
軟體環境:PostGIS(3.0.0rc2 r17909)和 PostgreSQL( 12.0, compiled by Visual C++ build 1914, 64-bit),數據是微軟開源的部分房屋數據public.california20191107(10988317條)。
預處理
預處理就是將3級到12級的矢量切片事先切好。首先獲取數據12級的最大最小xyz,通過這個範圍生成網格,然後和數據相交得到一一對應的網格表public.ca_xyz 。
--經度轉切片x
CREATE OR REPLACE FUNCTION lon2tile(lon DOUBLE PRECISION, zoom INTEGER)
RETURNS INTEGER AS
$BODY$
SELECT FLOOR( (lon + 180) / 360 * (1 << zoom) )::INTEGER;
$BODY$
LANGUAGE SQL IMMUTABLE;
--緯度轉切片y
CREATE OR REPLACE FUNCTION lat2tile(lat double precision, zoom integer)
RETURNS integer AS
$BODY$
SELECT floor( (1.0 - ln(tan(radians(lat)) + 1.0 / cos(radians(lat))) / pi()) / 2.0 * (1 << zoom) )::integer;
$BODY$
LANGUAGE sql IMMUTABLE;
--xyz轉幾何
create or replace function TileBBox (z int, x int, y int, srid int = 3857)
returns geometry
language plpgsql immutable as
$func$
declare
max numeric := 20037508.34;
res numeric := (max*2)/(2^z);
bbox geometry;
begin
bbox := ST_MakeEnvelope(
-max + (x * res),
max - (y * res),
-max + (x * res) + res,
max - (y * res) - res,
3857
);
if srid = 3857 then
return bbox;
else
return ST_Transform(bbox, srid);
end if;
end;
$func$;
--數據最大最小經緯度計算最大最小xyz
select lat2tile(ST_Y((pt).geom),12) y, lon2tile(ST_X((pt).geom),12) x FROM (SELECT ST_DumpPoints(ST_Extent(geom)) AS pt from public.california20191107) as foo where (pt).path[2] in (1,3)
--網格表
CREATE TABLE public.ca_xyz ( x integer,y integer,z integer,id integer NOT NULL ) WITH (OIDS = FALSE) TABLESPACE pg_default;
--示例
insert into public.ca_xyz (id,z,x,y) select 1,3,1,3 from public.california20191107 where TileBBox(3,1,3,4326)&&geom limit 1
接下來就比較簡單了,將quadkey生成3-11級xyz,把所有的xyz用來生成矢量切片。
--示例
SELECT ST_AsMVT(vt,'polygon',4096,'geo') tile FROM (SELECT ST_AsMVTGeom(geom,Box2D(TileBBox(3,1,3,4326)),4096,0,true) AS geo FROM public.california20191107 where TileBBox(3,1,3,4326)&&geom) AS vt
後臺服務
預處理矢量切片生成完以後,使用golang把矢量切片全部載入進程式中,並且建立鍵值對,能夠快速的判斷請求的xyz在3-12級是否有數據存在數據時能快速獲取。當數據請求大於12級時候,我們使用資料庫查詢方式獲取矢量切片。對於大於12級沒有緩存的數據會判斷是否是12級xyz的子級,如果是就會到資料庫查詢並緩存到程式中,如果不是就返回url無效減少資料庫查詢時間。