比較左連接和外部應用做同樣的事情
我在一個表上有一個更新觸發器,該觸發器在另一個數據庫/表中插入行
查詢看起來像
insert into otherdb.table select manyfield from inserted left join (select id, timestamp, row_number() over (partition by id order by timestamp desc) as rownum from sometable) as t1 on inserted.id = t1.id and rownum = 1
sometable有超過 700 萬行並且有適當的索引
在執行執行計劃時,我可以看到如果有 1 個更新的行,則視窗功能(使用正確的名稱?)檢索整個表對行編號並執行一次,它使用索引掃描
相同(它將檢索 700 萬行)如果插入有 20 行或插入有 50,000 行
現在該觸發器的使用主要是 1 行更新(我們確實有一些奇怪的情況,它將是 20-100 行甚至數千行)
我重構了這個查詢看起來像
insert into otherdb.table select manyfield from inserted outer apply join (select top 1 id, timestamp from sometable where inserted.id = sometable.id order by timestamp desc) as t1
最後的結果相同,但執行計劃發生了變化。
現在它正在使用索引搜尋,它會為每個插入的行返回 1 行
當我對 50,000 行進行大量更新時,執行計劃將告訴我執行左連接版本時的執行次數為 50,000而不是一個。
恢復一切;
左連接:所有插入的行都重用了 1 個大操作
外部應用:每個插入的行執行一次小操作
我的問題是,此時我對執行計劃的了解還不夠,無法決定我應該保留哪種連接,左連接還是外部應用?
這同時被 500-1000 個使用者使用,我們有超時錯誤可能與這個觸發器有關,我們目前使用左連接查詢
編輯
一些實際執行計劃的結果,選擇 55017 行
左連接:
估計子樹成本: ~78 記憶體授予: ~ 156k估計行數: ~57k
外用:
估計子樹成本: ~99 記憶體授予: ~163k 估計行數: ~55k
混合(狗仔隊的解決方案,但使用內連接,左連接見上文):
估計子樹成本: ~87 記憶體授予: ~170k 估計行數: ~56k
一些實際執行計劃的結果,更新 55017 行(觸發器)
左連接:
估計子樹成本: ~401 記憶體授權: ~455k 估計行數: ~225k
外用:
估計子樹成本: ~136 記憶體授予: ~153k 估計行數: ~52k
混合(狗仔隊的解決方案,但使用內連接,左連接見上文):
估計子樹成本: ~126 記憶體授予: ~ 156k估計行數: ~53k
試試這個 - 你可能會得到最好的
select manyfield from ( select manyfield , row_number() over (partition by t1.id order by t1.timestamp desc) as rownum from inserted left join sometable t1 on inserted.id = t1.id ) tt where rownum = 1 or t1.id is null