楼主: fromeast

利用rowid快速在线更新海量数据

[复制链接]
招聘 : 数据库管理员
论坛徽章:
66
ITPUB元老
日期:2005-07-16 18:49:11授权会员
日期:2005-10-30 17:05:33ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44现任管理团队成员
日期:2011-05-07 01:45:08版主3段
日期:2012-05-15 15:24:11
61#
发表于 2008-9-11 10:46 | 只看该作者
原帖由 棉花糖ONE 于 2008-9-11 10:43 发表


你看看楼主说的,楼主的意思是我读取了一行,然后我读取下一行的时候,这个块被flush出去,引起了不必要的物理读,用order by rowid避免了这问题


呵呵,你还在迷糊呢...

使用道具 举报

回复
招聘 : 数据库管理员
论坛徽章:
66
ITPUB元老
日期:2005-07-16 18:49:11授权会员
日期:2005-10-30 17:05:33ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44现任管理团队成员
日期:2011-05-07 01:45:08版主3段
日期:2012-05-15 15:24:11
62#
发表于 2008-9-11 10:48 | 只看该作者
还有n多种办法提高批量数据处理的速度...
假如需要在2个小时内处理完毕呢?楼主该如何处理?其实用不用rowid,都可以很快地处理完...

使用道具 举报

回复
论坛徽章:
27
会员2006贡献徽章
日期:2006-04-17 13:46:34奥运会纪念徽章:自行车
日期:2008-09-04 16:35:57数据库板块每日发贴之星
日期:2008-09-24 01:03:37生肖徽章2007版:鼠
日期:2008-11-14 12:38:47生肖徽章2007版:马
日期:2008-11-24 08:53:01生肖徽章2007版:羊
日期:2008-12-05 09:36:23生肖徽章2007版:龙
日期:2008-12-08 09:33:53八级虎吧徽章
日期:2008-12-08 16:10:58数据库板块每日发贴之星
日期:2008-12-09 01:01:05生肖徽章2007版:龙
日期:2009-03-16 17:39:22
63#
发表于 2008-9-11 10:49 | 只看该作者
原帖由 xzh2000 于 2008-9-11 10:48 发表
还有n多种办法提高批量数据处理的速度...
假如需要在2个小时内处理完毕呢?楼主该如何处理?其实用不用rowid,都可以很快地处理完...



这个我感兴趣,请说明

使用道具 举报

回复
论坛徽章:
138
19周年集字徽章-19
日期:2020-06-08 08:30:56马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:02路虎
日期:2013-11-22 12:26:18问答徽章
日期:2014-05-08 12:15:31
64#
发表于 2008-9-11 10:50 | 只看该作者
我们现在讨论的是,楼主这里到底是不是order by rowid起到了作用

使用道具 举报

回复
论坛徽章:
138
19周年集字徽章-19
日期:2020-06-08 08:30:56马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:02路虎
日期:2013-11-22 12:26:18问答徽章
日期:2014-05-08 12:15:31
65#
发表于 2008-9-11 10:51 | 只看该作者
原帖由 xzh2000 于 2008-9-11 10:48 发表
还有n多种办法提高批量数据处理的速度...
假如需要在2个小时内处理完毕呢?楼主该如何处理?其实用不用rowid,都可以很快地处理完...


请把n多种提高批量数据处理的方法都说说

使用道具 举报

回复
招聘 : 数据库管理员
论坛徽章:
66
ITPUB元老
日期:2005-07-16 18:49:11授权会员
日期:2005-10-30 17:05:33ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44现任管理团队成员
日期:2011-05-07 01:45:08版主3段
日期:2012-05-15 15:24:11
66#
发表于 2008-9-11 11:27 | 只看该作者
原帖由 棉花糖ONE 于 2008-9-11 10:50 发表
我们现在讨论的是,楼主这里到底是不是order by rowid起到了作用


当然是order by rowid起了作用...

使用道具 举报

回复
论坛徽章:
138
19周年集字徽章-19
日期:2020-06-08 08:30:56马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:02路虎
日期:2013-11-22 12:26:18问答徽章
日期:2014-05-08 12:15:31
67#
发表于 2008-9-11 11:30 | 只看该作者
原帖由 xzh2000 于 2008-9-11 11:27 发表


当然是order by rowid起了作用...


别这么肯定,能举个例子吗

使用道具 举报

回复
论坛徽章:
0
68#
发表于 2008-9-11 11:36 | 只看该作者

来看看我的方法,直接根据DBA_EXTENTS中的信息来更新

declare
maxrows number default 1000;
maxblocks number default 8;
v_partition_name varchar2(30);
v_relative_fno   number;
v_block_id       number;
v_blocks         number;
v_endblocks      number;
v_object_id      number;
rowid_table dbms_sql.Urowid_Table;
currcount_table dbms_sql.number_Table;
v_rowid         urowid;
v_rowid2        urowid;
cursor cur_extents is
       select PARTITION_NAME, RELATIVE_FNO, block_id, blocks
       from dba_extents a
       where a.owner = 'OWNER' and a.segment_name = 'T1'
       ORDER BY a.EXTENT_ID;
begin
  open cur_extents;
  LOOP
    EXIT WHEN cur_extents%NOTFOUND;
    FETCH cur_extents into v_partition_name, v_relative_fno, v_block_id, v_blocks;
    v_endblocks := 0;
    IF v_partition_name iS NULL THEN
       SELECT OBJECT_ID INTO v_object_id FROM dba_objects where owner = 'OWNER' AND OBJECT_NAME = 'T1'
              AND OBJECT_TYPE = 'TABLE';
    ELSE
        SELECT OBJECT_ID INTO v_object_id FROM dba_objects where owner = 'OWNER' AND OBJECT_NAME = 'T1'
               AND SUBOBJECT_NAME = v_partition_name AND OBJECT_TYPE = 'TABLE PARTITION';
    END IF;
   
    while v_endblocks < v_blocks loop
          v_rowid := dbms_rowid.rowid_create(1, v_object_id, v_relative_fno, v_block_id + v_endblocks, 0);
          v_endblocks := v_endblocks + maxblocks;
          if v_endblocks > v_blocks THEN
             v_rowid2 := dbms_rowid.rowid_create(1, v_object_id, v_relative_fno, v_block_id + v_blocks - 1, 1000);
          else
             v_rowid2 := dbms_rowid.rowid_create(1, v_object_id, v_relative_fno, v_block_id + maxblocks - 1, 1000);
          end if;              

   
          select /*+ ROWID(T1) */T1.ROWID, T2.curr_count
          bulk collect into rowid_table, currcount_table
          FROM OWNER.T1 T1, OWNER.T2 T2
          WHERE T1.ID2 = T2.ID2 and T1.rowid between v_rowid AND v_rowid2;

          forall i in 1 .. rowid_table.count
                 update OWNER.T1 set curr_count=currcount_table(i)
                 where rowid= rowid_table(i);
           commit;
    end loop;
  end loop;
  close cur_extents;
end;

其中查询语句中的提示可以根据具体情况进行调整

使用道具 举报

回复
论坛徽章:
131
2006年度最佳技术回答
日期:2007-01-24 12:58:48福特
日期:2013-10-24 13:57:422014年新春福章
日期:2014-02-18 16:41:11马上有车
日期:2014-02-18 16:41:11马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上加薪
日期:2014-02-19 11:55:142013年新春福章
日期:2013-02-25 14:51:24
69#
发表于 2008-9-11 13:12 | 只看该作者
1. 关于keep的问题,其实LZ写得很清楚,table 太大,不可能keep在内存中。

2. 为什么order by rowid 能起作用。想象一下一个极端情况,你的db_cache_size 很小,只够放一个table的block. 如果不用order by rowid, 那么,连续的每个更新的语句更新的row很有可能不在同一个block里。
如有这样的数据:
row1 : block 1
row2 : block 2
row3 : block 3
row4 : block 1
row5 : block 2
row6 : block 3
row7 : block 2
row8 : block 1

那么,逐条更新的话,每更新下一条都会导致前一个block被挤出去,相当于总共8个物理读。
而如果order by rowid
则会是这样子:
row1 : block 1
row2 : block 1
row3 : block 1
row4 : block 2
row5 : block 2
row6 : block 2
row7 : block 3
row8 : block 3
逐条更新的话,相当于3个物理读。

当然,实际情况可能更复杂,但是,总体来说,除非原始数据本来就按rowid/blockid排序,或者内存足够大,否则,order by rowid 并逐条更新的确会降低物理读(db file sequential read) .

其实可以自己构造一个测试来验证,紧记两点:
1。 内存尽量小
2。 原更新source的顺序尽量不合rowid排序

使用道具 举报

回复
论坛徽章:
138
19周年集字徽章-19
日期:2020-06-08 08:30:56马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-18 16:42:022014年新春福章
日期:2014-02-18 16:42:02路虎
日期:2013-11-22 12:26:18问答徽章
日期:2014-05-08 12:15:31
70#
发表于 2008-9-11 13:25 | 只看该作者
是的,楼主说的这情况出现说明buffer cache的使用已经很有问题了,而楼主keep了表,虽然不能keep住整个表,但是有可能这时候就算没有order by rowid,而楼主之前的那情况就已经没存在了

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表