天天看點

PostgreSQL multipolygon 空間索引查詢過濾精簡優化 - IO,CPU放大優化

PostgreSQL , PostGIS , 空間資料 , 多邊形 , bound box , R-Tree , GiST , SP-GiST

在PostgreSQL中,目前對于空間對象的索引,采用的是GiST索引方法,空間樹結構如下,每個ENTRY都是一個BOX:

PostgreSQL multipolygon 空間索引查詢過濾精簡優化 - IO,CPU放大優化

如果對象是多邊形,那麼在索引結構中,會存儲這個多邊形的bound box。

那麼對于非box類型,一定是會出現空間放大的。

PostgreSQL multipolygon 空間索引查詢過濾精簡優化 - IO,CPU放大優化

另一方面,如果輸入條件是個多邊形,那麼同樣會将這個多邊形的BOUND BOX作為輸入條件,根據查詢OP(操作符)到索引結構中找到這個輸入BOUND BOX的branch。

這樣,如果無效面積過多,就出現了索引掃描的IO放大和CPU放大。

例子如下:

優化方法是切割多邊形,減少無效空間,使用union all合并結果。

<a href="https://github.com/digoal/blog/blob/master/201710/20171004_01.md">《PostgreSQL 空間st_contains,st_within空間包含搜尋優化 - 降IO和降CPU(bound box) (多邊形GiST優化)》</a>

對于multi polygon對象,BOUND BOX就可能很大。

比如這個圖上的三個多邊形組成的multi polygon,實際上bound box是很大的。

PostgreSQL multipolygon 空間索引查詢過濾精簡優化 - IO,CPU放大優化

以上SQL,在使用GiST搜尋時,實際上會傳回這個bound box包含的所有空間對象,而不是這幾個小的多邊形包含的空間對象。然後在通過check filter來過濾。這樣就導緻了IO和CPU放大。

優化方法如上所述,SPLIT空間對象,多個空間搜尋結果UNION ALL得到最終結果。

1、建立測試表

2、寫入1000萬個空間點

3、建立空間索引

4、使用多個polygon構造成一個multi polygon

5、使用multi polygon搜尋

6、使用多個polgon搜尋,使用union all合并結果

7、寫UDF,簡化寫多個UNION ALL

使用UDF後,大大簡化了SQL寫法,同時性能得到了質的飛躍。

盡量的減少搜尋條件,或者資料本身的無效面積,可以降低IO和CPU,大幅提升性能。

<a href="https://github.com/digoal/blog/blob/master/201710/20171005_01.md">《PostgreSQL 空間切割(st_split)功能擴充 - 空間對象網格化 (多邊形GiST優化)》</a>

<a href="https://github.com/digoal/blog/blob/master/201709/20170905_01.md">《PostgreSQL 黑科技 - 空間聚集存儲, 内窺GIN, GiST, SP-GiST索引》</a>