Sql-Server
將兩個單獨的 UPDATE 合併為一個
我有兩個單獨的更新如下:
UPDATE mytab SET colA = 1 WHERE id IN ( SELECT id FROM mytab JOIN othertab ON mytab.otid = othertab.id WHERE othertab.Lock = 'SomeLock' AND mytab.colA IS NULL); UPDATE mytab SET colB = 2 WHERE id IN ( SELECT ID FROM mytab JOIN othertab ON mytab.otid = othertab.id WHERE othertab.Lock = 'SomeLock' AND mytab.colB IS NULL);
我希望它們作為一個合併的 UPDATE 查詢。我所做的是:
UPDATE mytab SET colA = CASE WHEN colA IS NULL THEN 1 ELSE colA END, colB = CASE WHEN colB IS NULL THEN 2 ELSE colB END WHERE id IN ( SELECT id FROM mytab JOIN othertab ON mytab.otid = othertab.id WHERE othertab.Lock = 'SomeLock');
一般來說,它在 SQL Server 和 Oracle 上都能滿足我的要求。我在這里關心的是合併查詢的性能。在該形狀中,它將更新按謂詞過濾後返回的每一行。有更好的解決方案嗎?
我對 Oracle 的了解不夠多,無法知道以下是否是有效的語法……或者是否有特定於該 RDBMS 的更巧妙的技巧。但是,在 SQL Server 上,我會做這樣的事情。
/** If you are updating small numbers of rows then this is probably good enough on SQL Server. Properly indexed tables, etc. **/ UPDATE mytab SET colA = COALESCE(colA, 1) , colB = COALESCE(colB, 2) WHERE EXISTS (SELECT TOP (1) 1 FROM othertab WHERE othertab.id = mytab.otid AND othertab.Lock = 'SomeLock') AND ( colA IS NULL OR colB IS NULL ) /** Larger numbers of rows could do better like this. **/ UPDATE M SET colA = COALESCE(colA, 1) , colB = COALESCE(colB, 2) FROM mytab AS M INNER JOIN othertab AS O ON O.id = M.otid AND O.Lock = 'SomeLock' WHERE M.ColA IS NULL OR M.ColB IS NULL
如果超過 20% 的行被修改,可能會有更好的方法。
甲骨文
merge into mytab a using ( select c.id ,coalesce( c.colA, 1 ) as colA ,coalesce( c.colB, 2) as colB -- Oracle performance might improve with NVL() instead of coalesce from mytab c join othertab d on c.otid = d.id where d.lock = 'SomeLock' and ( c.colA is null or c.colB is null ) ) b on ( a.id = b.id ) when matched then update set a.colA = b.colA ,a.qoh = b.colB;
提示可能有助於進一步
/*+ parallel */
改進
- 僅當新語句不夠快時才嘗試。
DBMS_PARALLEL_EXECUTE
可以幫助最小化 UNDO 空間
- 不要將兩者混合
SQL 伺服器
{這裡放程式碼}