我如何(高效地)在昂貴的表格表達式上執行多個選擇?通過昂貴的表格表達式掃描多個選項
我有一個表,像這樣
CREATE TABLE facts (
subject_id INT,
visit_id INT,
study_id INT,
provider_id INT,
variable_id INT,
value TEXT
)
即各行的結構是,具有許多尺寸和值的測量。 facts
表很大,但每個維度都小得多,例如, SELECT DISTINCT subject_id FROM facts
的基數可能是幾百。
現在我想找到一個事實子集的獨特維度值,即不同主體,訪問,提供者和變量study_id = X的ID。這很容易通過做多個查詢來查詢,如在
SELECT DISTINCT subject_id FROM facts WHERE study_id = X;
SELECT DISTINCT visit_id FROM facts WHERE study_id = X;
SELECT DISTINCT provider_id FROM facts WHERE study_id = X;
SELECT DISTINCT variable_id FROM facts WHERE study_id = X;
但是,每個查詢然後必須對facts
表(或索引)執行單獨掃描。 (SELECT * FROM facts WHERE study_id = X
的基數也很大,儘管不如整個表大)。
是否有某種方法可以組合這些查詢,以便數據庫只需對facts
表執行一次掃描並收集所有不同的維度ID的一次去?
到目前爲止,我嘗試使用公共表格表達式,但仍然導致(在Postgres中)在CTE上進行多次掃描,因此它沒有幫助。 e.g:
WITH selected AS (SELECT * FROM facts WHERE study_id = X)
SELECT DISTINCT subject_id, 1 FROM selected
UNION ALL SELECT DISTINCT visit_id, 2 FROM selected
UNION ALL SELECT DISTINCT provider_id, 3 FROM selected
UNION ALL SELECT DISTINCT variable_id, 4 FROM selected
有什麼辦法有DB只做單次掃描在facts
,並收集所有需要的結果嗎?我特別感興趣的是Postgres和Oracle的支持。
「*但仍然導致在CTE *多次掃描」當然,當你選擇它多次,它的作用。數據庫**有**可以多次掃描。但是,如果選擇的結果足夠小,那麼這些「掃描」將完全在內存中完成 - 如果您需要儘快更新,請在Postgres中增加「work_mem」。 '解釋(分析,詳細,緩衝)'會告訴你,如果這是在內存中完成的。 –
'select array_agg(distinct subject_id)as subject_ids,array_agg(distinct visit_id)as visit_ids,... from facts where study_id = x;' - 它用於PostgreSQL – Abelisto
@a_horse_with_no_name數據庫不必多次掃描,如果優化器足夠聰明。數據庫可以自由使用任何查詢策略,只要它提供了正確的答案。在我的情況下,CTE可能仍然太大,無法保存在內存中,這取決於同時發生的其他事情。 – JanKanis