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;