本文介紹了是否有可能對運行總數編制索引以加快窗口函數的運行速度?的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!
問題描述
我要執行:
SELECT cust_id, SUM(cost)
FROM purchases
WHERE purchase_time BETWEEN('2018-01-01', '2019-01-01')
GROUP BY cust_id
但是對于大量的行,我預計必須加載每條記錄才能聚合相應的總和。我想做的是有一個類似于:
的索引
CREATE INDEX purchase_sum
ON purchases(cust_id, purchase_time,
SUM(cost) OVER (PARTITION BY cust_id
ORDER BY purchase_time) AS rolling_cost)
我想要一個如下所示的索引:
cust_id time rolling_cost
-------- ------ --------------
1 Jan 1 5
1 Jan 2 12
1 Jan 3 14
1 Jan 4 20
1 Jan 5 24
2 Jan 1 1
2 Jan 2 7
2 Jan 3 11
2 Jan 4 14
2 Jan 5 19
3 Jan 1 4
3 Jan 2 5
3 Jan 3 10
3 Jan 4 21
3 Jan 5 45
從這里,我的原始查詢可以通過簡單地將每個cust_id減去2個已知值來計算,大致為cost_in_window = rolling_cost('2019-01-01') - rolling_cost('2018-01-01')
,這將不需要從源表加載任何東西。
這作為索引可行嗎?或者,有沒有其他方法來實現同樣的目標?
推薦答案
您可能會發現這樣更快:
select c.cust_id,
(select sum(p.cost)
from purchases p
where p.cust_id = c.cust_id and
p.purchase_time >= '2018-01-01' and
p.purchase_time < '2019-01-01' and
) as total_cost
from customers c
having total_cost is not null;
然后,可以使用purchases(cust_id, purchase_time, cost)
上的索引。僅計算金額時需要該索引。這是一筆省錢。更重要的是,沒有整體匯總–這可能是對所有客戶進行計算所節省的更大成本。
但是,對于相同的索引,這可能會更好一些:
select c.cust_id,
(select sum(p.cost)
from purchases p
where p.cust_id = c.cust_id and
p.purchase_time >= '2018-01-01' and
p.purchase_time < '2019-01-01'
) as total_cost
from customers c
where exists (select 1
from purchases p
where p.cust_id = c.cust_id and
p.purchase_time >= '2018-01-01' and
p.purchase_time < '2019-01-01'
);
編輯:
實現所需內容的唯一方法是在數據中顯式包含一個累計和列。這將需要重新組織查詢(進行您想要的減法),并使用觸發器來維護值。
如果歷史數據永遠不變,這可能是一種合理的方法。但是,更新或插入較早的行可能會變得非常昂貴。
這篇關于是否有可能對運行總數編制索引以加快窗口函數的運行速度?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,