指數
創建於x.id
和y.id
指數 - 你可能已經有了,如果這些是你的主鍵。
多列索引可能會有幫助,太,尤其是在index only scans PG 9.2+:
CREATE INDEX y_mult_idx ON y (id DESC, val)
然而,在我的測試中,該指數是在沒有首先使用。必須添加(否則毫無意義)val
到ORDER BY
以說服查詢規劃器排序順序匹配。見查詢。
該指數在這個合成設置中幾乎沒有什麼區別。但是對於列數更多的表格,從表中檢索val
變得越來越昂貴,使得「覆蓋」索引更具吸引力。
查詢
1)簡單
SELECT DISTINCT ON (x.id)
x.id, y.val
FROM x
JOIN y ON y.id <= x.id
ORDER BY x.id, y.id DESC;
SQL Fiddle.
在這個相關答案與
DISTINCT
技術
更多的解釋:
我跑了一些測試,因爲我懷疑第一個查詢不能很好地擴展。它有一張小桌子很快,但桌子較大時沒有好處。 Postgres沒有優化計劃,並以(有限)交叉連接開始,成本爲O(N²)
。
2)快速
這個查詢仍然是相當簡單,並且很好地磅秤:
SELECT x.id, y.val
FROM x
JOIN (SELECT *, lead(id, 1, 2147483647) OVER (ORDER BY id) AS next_id FROM y) y
ON x.id >= y.id
AND x.id < y.next_id
ORDER BY 1;
窗口函數lead()
是工具。我使用該選項來提供默認設置以覆蓋最後一行的轉角情況:2147483647
是biggest possible integer。適應你的數據類型。
3)非常簡單和幾乎一樣快
SELECT x.id
,(SELECT val FROM y WHERE id <= x.id ORDER BY id DESC, val LIMIT 1) AS val
FROM x;
通常,相關子查詢往往較慢。但是這隻能從(覆蓋)指數中選擇一個價值,否則就很容易競爭。
額外的ORDER BY
項目val
(大膽強調)似乎毫無意義。但是添加它會使查詢規劃人員相信,使用上面的多列索引y_mult_idx
是可以的,因爲排序順序是匹配的。注意
只索引掃描使用y_mult_idx ..
在
EXPLAIN
輸出
。
測試用例
展開了熱烈討論,並多次更新我收集到的所有查詢到目前爲止發佈和簡要概述做了一個試驗案例後。我只使用1000行,所以SQLfiddle不會超時較慢的查詢。但前4名(Erwin 2,Clodoaldo,a_horse,Erwin 3)在我所有的本地測試中線性縮放。 更新一次,包括我的最新加入,現在改善性能的格式和順序:
Big SQL Fiddle comparing performance.
只有應用排序順序時,才能識別「下一個」行。 「下一個」是指具有更高「id」的行嗎? – 2013-04-07 10:53:36
是的,我已經更新了示例查詢以添加'by x.id'的訂單。 – jl6 2013-04-07 10:55:26
您的示例表明值也按升序排列。是這樣嗎? – 2013-04-07 12:47:23