空間連接
空間連接(spatial joins)是空間數據庫的主要組成部分,它們允許你使用空間關系作為連接鍵(join key)來連接來自不同數據表的信息,如:
SELECT
subways.name AS subway_name,
neighborhoods.name AS neighborhood_name,
neighborhoods.boroname AS borough
FROM nyc_neighborhoods AS neighborhoods
JOIN nyc_subway_stations AS subways
ON ST_Contains(neighborhoods.geom, subways.geom)
WHERE subways.name = 'Broad St';
任何在兩個表之間提供true/false關系的函數都可以用來驅動空間連接,但最常用的函數是:
ST_Intersects、ST_Contains和ST_DWithin
默認情況下,數據庫使用的是INNER JOIN連接類型,還可以用 LEFT OUTER JOIN、RIGHT OUTER JOIN
創建和使用索引
如下創建一個空間索引:
CREATE INDEX nyc_census_blocks_geom_idx
ON nyc_census_blocks
USING GIST (geom)
USING GIST子句告訴PostgreSQL在構建索引時使用generic index structure(GIST-通用索引結構)
PostGIS使用"R-Tree"空間索引結構。R-Tree將數據分解為矩形(rectangle)、子矩形(sub-rectangle)和子-子矩形(sub-sub rectangle)等。它是一種可自動處理可變數據的密度和對象大小的自調優(self-tuning)索引結構。
對於一個大的數據表來說,先計算出近似結果,然后進行精確測試的"兩遍"機制可以從根本上減少計算量。(這種思想就是粗調和精調的思想,就像顯微鏡一樣有粗粒度的調整和細粒度的調整。很多事物都涉及到這個思想,它的作用就是減少了耗費的代價)
使用索引:
-
純索引查詢:使用"&&"運算符。對於幾何圖形,&&運算符表示"邊界框重疊或接觸"(純索引查詢),就像對於數字,"="運算符表示"值相同"。
SELECT Sum(popn_total)
FROM nyc_neighborhoods neighborhoods
JOIN nyc_census_blocks blocks
ON neighborhoods.geom && blocks.geom
WHERE neighborhoods.name = 'West Village';
-
PostGIS中最常用的函數(ST_Contains、ST_Intersects、ST_DWithin等)都包含自動索引過濾器
-
有些函數(如ST_Relate)不包括索引過濾器
分析(ANALYZE)
PostgreSQL查詢規划器(query planner)智能地選擇何時使用或不使用空間索引來計算查詢。與直覺相反,執行空間索引搜索並不總是更快:如果搜索將返回表中的每條記錄,則遍歷索引樹以獲取每條記錄實際上比從一開始線性讀取整個表要慢(注意這句話)。
為了弄清楚要處理的數據的大概內容(讀取表的一小部分信息,而不是讀取表的大部分信息),PostgreSQL保存每個索引列中數據分布的統計信息。默認情況下,PostgreSQL定期收集統計信息。但是,如果你在短時間內更改了表的構成,則統計數據將不會是最新的。
為確保統計信息與表內容匹配,明智的做法是在表中加載和刪除大容量數據后手動運行ANALYZE命令。這將強制統計系統收集所有索引列的統計信息。
ANALYZE命令要求PostgreSQL遍歷該表並更新用於查詢操作而估算的內部統計信息。
ANALYZE nyc_census_blocks;
清理(VACUUM)
值得強調的是,僅僅創建空間索引不足以讓PostgreSQL有效地使用它。每當創建新索引或對表大量更新、插入或刪除后,都必須執行清理(VACUUMing)。VACUUM命令要求PostgreSQL回收表頁面中因記錄的更新或刪除而留下的任何未使用的空間。
清理對於數據庫的高效運行非常關鍵,因此,PostgreSQL提供了一個“自動清理(autovacuum)"選項。
默認情況下,自動清理機制會根據活動級別確定的合理時間間隔自動清理(恢復空間)和分析(更新統計信息)。雖然這對於高度事務性的數據庫是必不可少的功能,但在添加索引或大容量數據之后等待自動清理運行是不明智的,如果執行大批量更新,則應該手動運行VACUUM命令。
根據需要,可以單獨執行清理和分析。發出VACUUM命令不會更新數據庫統計信息;同樣,執行ANALYZE命令也不會清理未使用的表空間。這兩個命令都可以針對整個數據庫、單個表或單個列運行。
VACUUM ANALYZE nyc_census_blocks;