Sql 这就是MERGE的作用。建议的索引和要更新的MERGE语句如何?@Aishu。那也没关系。我不知道你为什么建议第一个索引的顺序,因为在我的WHERE中,我首先检查t2.升级版本,然后检查t2.操作,最后检查t2.项目id。为什么不为原始查询使用staged
Sql 这就是MERGE的作用。建议的索引和要更新的MERGE语句如何?@Aishu。那也没关系。我不知道你为什么建议第一个索引的顺序,因为在我的WHERE中,我首先检查t2.升级版本,然后检查t2.操作,最后检查t2.项目id。为什么不为原始查询使用staged,sql,oracle,Sql,Oracle,这就是MERGE的作用。建议的索引和要更新的MERGE语句如何?@Aishu。那也没关系。我不知道你为什么建议第一个索引的顺序,因为在我的WHERE中,我首先检查t2.升级版本,然后检查t2.操作,最后检查t2.项目id。为什么不为原始查询使用staged\u项目(升级版本、操作、项目id)order?你能详细说明一下吗?另外,我想你想在你建议的第一个索引中说item\u id,而不是id。好吧,也许我的问题很傻,因为where子句中的条件顺序并不重要。我想了解的是,你提出的两个不同的指数背后的
这就是
MERGE
的作用。建议的索引和要更新的MERGE语句如何?@Aishu。那也没关系。我不知道你为什么建议第一个索引的顺序,因为在我的WHERE
中,我首先检查t2.升级版本
,然后检查t2.操作
,最后检查t2.项目id
。为什么不为原始查询使用staged\u项目(升级版本、操作、项目id)
order?你能详细说明一下吗?另外,我想你想在你建议的第一个索引中说item\u id
,而不是id
。好吧,也许我的问题很傻,因为where子句中的条件顺序并不重要。我想了解的是,你提出的两个不同的指数背后的想法是什么。您希望外部where的版本有什么改进?cur\u upd[i]。row\u id
不是有效的Oracle语法。另外,当您使用ROWID
时,您应该始终使用FOR UPDATE
子句定义光标,以确保记录被锁定。我怀疑逐行更新是否比单个UPDATE语句更快。@WernfriedDomscheit我认为运行从数亿行中提取的单个更新,不知道你在这个过程中处于什么位置,是一个更大的问题。如果像我所描述的那样使用初始mat视图(或者甚至是通过CTAS使用的常规表),您会感到惊讶。建议使用CTAS时+1。无论如何,我不太确定这是我的问题,因为在我的测试用例中,staged\u项的大多数行与查询匹配,而且更新速度很慢。另外,我考虑使用rownum多次批处理更新,每次都使用固定数量的行,而不是逐行处理。
UPDATE items t1
SET (name, manufacturer_id, price) =
(SELECT
t2.item_name,
t2.item_manufacturer_id,
t2.item_price
FROM staged_items t2
WHERE t2.upgrade_version = 1234
AND t2.operation = 'modification'
AND t1.id = t2.item_id)
WHERE EXISTS (
SELECT 1
FROM staged_items t2
WHERE t2.upgrade_version = 1234
AND t2.operation = 'modification'
AND t1.id = t2.item_id)
UPDATE items t1
SET (name, manufacturer_id, price) =
(
SELECT
t2.item_name,
t2.item_manufacturer_id,
t2.item_price
FROM
(
SELECT /*+ FIRST_ROWS(n) */
a.*,
ROWNUM rnum
FROM
(
SELECT *
FROM staged_items t2
WHERE t2.upgrade_version = 1234
AND t2.operation = 'modification'
AND t1.id = t2.item_id
ORDER BY t2.id
) a
WHERE ROWNUM <= MAX_ROW_TO_FETCH
)
WHERE rnum >= :MIN_ROW_TO_FETCH
)
WHERE EXISTS (
SELECT 1
FROM staged_items t2
WHERE t2.upgrade_version = 1234
AND t2.operation = 'modification'
AND t1.id = t2.item_id)
staged_items(item_id, upgrade_version, operation)
WHERE t1.id IN (SELECT t2.item_id
FROM staged_items t2
WHERE t2.upgrade_version = 1234 AND t2.operation = 'modification'
)
create table log_load(table_name varchar2(50), create_date date, message varchar2(500));
declare
cursor cur_upd is
SELECT rowid as row_id
FROM items t1
WHERE EXISTS (
SELECT 1
FROM staged_items t2
WHERE t2.upgrade_version = 1234
AND t2.operation = 'modification'
AND t1.id = t2.item_id);
TYPE fetch_array IS TABLE OF cur_upd%ROWTYPE;
s_array fetch_array;
BEGIN
insert into log_load values ('item',sysdate,'Start')
commit;
OPEN cur_upd;
upd_ := 0;
LOOP
FETCH cur_upd BULK COLLECT INTO s_array LIMIT 50000;
upd_ := upd_ + s_array.COUNT;
FORALL i IN 1..s_array.COUNT
UPDATE items t1
SET (name, manufacturer_id, price) =
(SELECT t2.item_name, t2.item_manufacturer_id, t2.item_price
FROM staged_items t2
WHERE t2.upgrade_version = 1234
AND t2.operation = 'modification'
AND t1.id = t2.item_id)
WHERE t1.rowid = cur_upd[i].row_id;
insert into log_load values ('item',sysdate,'50000 updated.')
commit;
EXIT WHEN cur_upd%NOTFOUND;
END LOOP;
CLOSE cur_upd;
insert into log_load values ('item',sysdate,'end');
commit;
END;
UPDATE
(SELECT t1.name, t1.manufacturer_id, t1.price,
t2.item_name,
t2.item_manufacturer_id,
t2.item_price,
t1.id, t2.item_id
from items t1
JOIN staged_items t2 on t1.id = t2.item_id
WHERE t2.upgrade_version = 1234
AND t2.operation = 'modification')
SET name = item_name,
manufacturer_id = item_manufacturer_id,
price = item_price;
SELECT
t2.item_name,
t2.item_manufacturer_id,
t2.item_price
FROM staged_items t2
WHERE t2.upgrade_version = 1234
AND t2.operation = 'modification'
declare
cursor sel_stage_mv is
select * from my_stage_mv;
l_cnt pls_integer := 0;
l_upd_cnt pls_integer := 0;
begin
for rec in sel_stage_mv
loop
l_cnt := l_cnt + 1;
-- all needed indexes are on main table (id, etc...)
update main_table
set ...
where id = rec.id;
l_upd_cnt := l_upd_cnt + SQL%ROWCOUNT;
if (mod(l_cnt, 10000) = 0) then
-- insert to some log table via autonomous procedure
ins_log(...l_upd_cnt ...);
commit;
end if;
end loop;
commit;
end;