2014-03-30 52 views
0

多行陣列我有兩個表:PostgreSQL的 - 創建和加入基於ID

LINKS有:

LINK_ID --- integer, unique ID 
FROM_NODE_X -- numbers/floats, indicating a geographical position 
FROM_NODE_Y -- 
FROM_NODE_Z -- 
TO_NODE_X -- 
TO_NODE_Y -- 
TO_NODE_Z -- 

LINK_COORDS有:

LINK_ID --- integer, refers to above UID 
ORDER --- integer, indicating order 
X --- 
Y --- 
Z --- 

邏輯上,每個LINK由多個航點組成。最終的順序是:

FROM_NODE , 1 , 2 , 3 , ... , TO_NODE 

鏈路具有至少兩個路點(FROM_NODE,TO_NODE),但可以有在它們之間具有可變數量的路點(0至100+)。

我現在需要一種方法來聚合,排序和存儲數組中每個鏈接的航點,以後將用於繪製一條線。

我很努力地將LINK_COORDS作爲單獨的行提供。在其他(LINKS)表中具有開始和結束位置也無濟於事。如果我有辦法至少讓所有LINK_COORDS加入/更新到LINKS表格中,我可能會再次自己解決其他問題。所以,如果你對如何獲得這樣的想法有所瞭解,那就已經非常感激了。

考慮到性能會很好(表格現在介於500k到1mio之間,稍後會有倍數),但現在並不重要。

編輯: 感謝您的建議,馬與沒有名稱。 在這一步之前,我選擇爲每個XYZ創建點幾何圖形(PostGIS),因此最後只有從各個點創建的點陣列。 的適於SQL

UPDATE "Link" 
SET "POINTS" = 
    array_append(
     (array_prepend(
      "FROM_POINT", 
      (SELECT array_agg(lc."POINT" ORDER BY lc."COUNT") 
       FROM "LinkCoordinate" lc 
       WHERE lc."LINK_ID" = "Link"."LINK_ID"))) 
     , "TO_POINT") 

然而極其緩慢運行: 運行它示例性10個鏈接所需的〜120秒。爲所有1,3mio鏈接運行它,以及更多linkcoords可能需要大約半年左右的時間。不是很理想。

我怎樣才能找出這巨大的緩慢起源?

如果我以預定義的格式獲得源數據(所以每個link_ID的linkcoordinates),這將允許我顯着加快SQL查詢嗎?

編輯:看起來主要的減速來自array_agg()函數中使用的SELECT子查詢。其他一切(包括訂購)並不會真正導致任何放緩。

我目前的猜測是,SELECT查詢迭代「LinkCoordinate」爲每一個環節的整體上,使其更加努力比它,屬於一個連接所有LinkCoordinates都總是存儲在'塊'的行。真正的,LinkCordinates的單個順序處理就足夠了。

回答

0

像這樣也許:

select l.link_id, 
     min(l.from_node_x) as from_node_x, 
     min(l.from_node_y) as from_node_y, 
     min(l.from_node_z) as from_node_z, 
     array_agg(lc.x order by lc."ORDER") as points_x, 
     array_agg(lc.y order by lc."ORDER") as points_y, 
     array_agg(lc.z order by lc."ORDER") as points_z, 
     min(l.to_node_x) as to_node_x, 
     min(l.to_node_y) as to_node_y, 
     min(l.to_node_z) as to_node_z 
from links l 
    join link_coords lc on lc.link_id = l.link_id 
group by l.link_id; 

min()是必要的,因爲在group by但不會改變結果從links所有值都是一樣的呢。

另一種可能性是使用標量子查詢。我不確定他們哪一個更快 - 但加入/分組可能更有效。

select l.link_id, 
     l.from_node_x, 
     l.from_node_y, 
     l.from_node_z, 
     (select array_agg(lc.x order by lc."ORDER") from link_coords lc where lc.link_id = l.link_id) as points_x, 
     (select array_agg(lc.y order by lc."ORDER") from link_coords lc where lc.link_id = l.link_id) as points_y, 
     (select array_agg(lc.z order by lc."ORDER") from link_coords lc where lc.link_id = l.link_id) as points_z, 
     l.to_node_x, 
     l.to_node_y, 
     l.to_node_z 
from links l