我有2個表(不能更改)SQL Server的親子加入和緩慢的查詢性能
Parent (id, date, amount)
Child (parent_id, key, value)
指標
Parent.pk (id)
Parent.idx1 (id, date) include (amount)
Child.pk (parent_id, key)
Child.idx1 (parent_id, key, value)
和查詢
select sum(amount)
from Parent as p
left outer join Child as c1 on c1.parent_id = p.id and c1.key = 'X'
left outer join Child as c2 on c2.parent_id = p.id and c2.key = 'Y'
where p.date between '20120101' and '20120131'
and c1.value = 'x1'
and c2.value = 'y1'
問題是性能。
家長有〜1個500 000記錄和子〜6 000 000條記錄
以1
這個查詢大約需要3秒是太多了我的情況 - 它必須比幾毫秒的時間少。
執行計劃顯示我的SQL Server正在做Parent.idx1
索引掃描,比合並與Child.idx1
聚集索引加入尋求 - 因爲它,當我按日期過濾它們掃描整個150萬點的記錄,即使這不是最佳的。
取2
當我改變Parent.idx1
到
Parent.idx1 (date, id) include (amount)
的SQL Server選擇聚集索引掃描Parent.pk
比再次合併與Child.idx1
加入。執行時間約爲6秒。
取3
當我強制使用Parent.idx1 (date, id) include (amount)
然後排序結果前合併連接和執行時間還差〜11S。
以4
試圖創建索引視圖,但JOIN不能使用它,因爲左外。
有沒有什麼辦法可以做出這樣的查詢 - Parent-Child與它們兩個上的過濾器連接 - 更快?
沒有反規範化。
更新2013年7月4日:
要回答那些使用INNER JOIN - 是它的速度更快,但我不能使用它。
我在這裏展示的是我真正需要的簡化版本。
我需要爲MS動態導航「總帳條目」(父)和「總帳條目維度」(子)表創建SQL視圖,以便我能夠從該應用程序讀取它。 完整視圖貌似現在這種權利:
create view analysis
as
select
v.id as view_id
, p.date
, p.Amount
, c1.value as value1
, c2.value as value2
, c3.value as value3
, c4.value as value4
from Parent as p
cross join analysis_view as v
left outer join Child as c1 on c1.parent_id = p.id and c1.key = v.key1
left outer join Child as c2 on c2.parent_id = p.id and c2.key = v.key2
left outer join Child as c3 on c3.parent_id = p.id and c3.key = v.key3
left outer join Child as c4 on c4.parent_id = p.id and c4.key = v.key4
其中analysis_view包含8條記錄當前,看起來像這樣:analysis_view (id, key1, key2, key3, key4)
然後aplication可以查詢它像這樣
select sum(amount)
from analysis
where view_id = 1 and date between '20120101' and '20120131'
and value1 = 'x1'
and value2 = 'x2'
或
select sum(amount)
from analysis
where view_id = 1 and date between '20120101' and '20120131'
and value1 = 'x1'
and value3 = 'z1'
MS動態資產淨值已對其進行了非標準化表格以及來自其的查詢速度很快,但在我們的情況下(〜10GB)非常巨大,並且在somone創建新的分析視圖時將整個系統鎖定約一個小時。 另外NAV不知道如何產生連接,這就是爲什麼我必須在SQL Server端定義它。
「X」和「Y」是「key」的唯一值嗎? –
如果它有一個X鍵和一個Y鍵的孩子,你是否應該計算兩次記錄的數量?或者如果它有一個X或Y的孩子,你是否應該使用該數額進行求和?因爲你在做第一個,但第二個更常見。 –
「少於幾毫秒」意味着所有需要的數據都將處於高速緩存中,或者任何I/O都將完成到SSD,可能位於RAID集中以提高讀取帶寬。 – HABO