29. 最鄰近搜尋

29.2. 最鄰近連接

由操作員協助的索引順序有一個主要的缺點:它只適用於操作員單側的一個 **單一幾何文字** 。這對於尋找最接近一個查詢對象的物件來說很好,但對於一個目標是要找到所有候選者當中每個鄰近點的空間聯結則沒有幫助。

幸運的是,SQL 語言有一個功能允許我們反覆執行一個查詢並在迴圈中驅動:LATERAL 聯結

在這裡,我們將找到最接近每個地鐵站的街道

SELECT subways.gid AS subway_gid,
       subways.name AS subway,
       streets.name AS street,
       streets.gid AS street_gid,
       streets.geom::geometry(MultiLinestring, 26918) AS street_geom,
       streets.dist
FROM nyc_subway_stations subways
CROSS JOIN LATERAL (
  SELECT streets.name, streets.geom, streets.gid, streets.geom <-> subways.geom AS dist
  FROM nyc_streets AS streets
  ORDER BY dist
  LIMIT 1
) streets;

請注意,像 CROSS JOIN LATERAL 這樣的方式作為由地鐵表格驅動的迴圈的內部。地鐵表格中的每筆記錄都會一次一個的提供給 lateral 次查詢,所以每個地鐵記錄都可以得到一個最近的結果。

_images/knn4.png

說明解釋了地鐵站上的迴圈,和在我們想要的迴圈內部的索引協助訂購

                           QUERY PLAN
-------------------------------------------------------------------------
 Nested Loop  (cost=0.28..13140.71 rows=491 width=37)
   ->  Seq Scan on nyc_subway_stations subways
       (cost=0.00..15.91 rows=491 width=46)
   ->  Limit
       (cost=0.28..1.71 rows=1 width=170)
         ->  Index Scan using nyc_streets_geom_idx on nyc_streets streets
             (cost=0.28..27410.12 rows=19091 width=170)
                Order By: (geom <-> subways.geom)