以前作的海量數據數據展現,在預處理速度和在線渲染上還有有所欠缺,本文中進行一些優化工做,使得九分鐘處理完一千多萬面數據的3-12級矢量切片,在線瀏覽數據請求時間控制在10s左右。golang
軟件環境:PostGIS(3.0.0rc2 r17909)和 PostgreSQL( 12.0, compiled by Visual C++ build 1914, 64-bit),數據是微軟開源的部分房屋數據public.california20191107(10988317條)。sql
預處理就是將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無效減小數據庫查詢時間。
優化