楼主: looric

UPDATE 160 million ROWS HOW TO?

[复制链接]
论坛徽章:
90
数据库板块每日发贴之星
日期:2005-04-25 01:01:202014年新春福章
日期: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:142014年世界杯参赛球队: 美国
日期:2014-06-06 14:24:30马上有对象
日期:2014-10-21 13:39:03
11#
 楼主| 发表于 2005-4-26 18:34 | 只看该作者
呵呵,我更新了6个分区,花了60分钟。实在忍受不了了,就取消了。现在我要更新回去。
[php]
DECLARE
  pa_num NUMBER;
  pa_rec DBA_TAB_PARTITIONS.PARTITION_NAME%TYPE; -- declare record variable  
  CURSOR c0 IS
    select PARTITION_NAME
      from DBA_TAB_PARTITIONS A
     where table_name = 'SM_CALLRECORD'
       AND SUBSTR(A.PARTITION_NAME, 3, 8) BETWEEN '20041002' AND '20050101'
     order by PARTITION_NAME;
  MY_CALLTIME SM_CALLRECORD.CALLTIME%TYPE;
BEGIN
  open c0;
  pa_num := 1;
   LOOP
    fetch c0
      into pa_rec;
    EXIT WHEN c0%NOTFOUND;
    dbms_output.put_line(sysdate || 'Updating ' || pa_rec ||
                         ' PARTITION_NAME' || '-p' || pa_num || '.');
    execute immediate 'UPDATE  /*+ PARALLEL(N,2) */ SM_CALLRECORD partition(' ||
                      pa_rec || ')
     SET CALLTIME = to_char((to_date(calltime,''yyyymmddhh24miss'')+8/24),''yyyymmddhh24miss'')';
    commit;
    dbms_output.put_line(sysdate || 'Updated ' || pa_rec ||
                         ' PARTITION_NAME' || '-p' || pa_num || '.');
    pa_num := pa_num + 1;
  END LOOP;
  close c0;
END;
[/php]

使用道具 举报

回复
论坛徽章:
90
数据库板块每日发贴之星
日期:2005-04-25 01:01:202014年新春福章
日期: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:142014年世界杯参赛球队: 美国
日期:2014-06-06 14:24:30马上有对象
日期:2014-10-21 13:39:03
12#
 楼主| 发表于 2005-4-27 08:48 | 只看该作者
Undo Tablespace Size and Retention Time
In order for changes to be rolled back or undone, Oracle makes a copy of the original data before modifying it. The original copy of the modified data is called undo data. Undo data is stored in a logical database structure called an undo tablespace.

The undo tablespace is of a finite size. Space usage within the tablespace is such that records can be overwritten. The undo data needs to be saved at least until the transaction has been committed. Until then the undo data is said to be in the active state. The amount of space available in the undo tablespace should, therefore, be at least large enough to hold the active undo data generated by currently active transactions. Otherwise some of these transactions may fail. After the active undo data is stored in the undo tablespace, Oracle automatically ensures that it is never overwritten until the corresponding transaction has been committed.

Even after the transaction has been committed, the undo data still cannot be overwritten immediately. It is important to the success of flashback functionality, and for read consistency for long running transactions, that records not be overwritten too soon. For example, if your longest query takes 15 minutes, the undo tablespace should be big enough to hold 15 minutes worth of undo information.
所以不论分区不分区提交都不会节省Undo Tablespace

使用道具 举报

回复
论坛徽章:
43
会员2007贡献徽章
日期:2007-09-26 18:42:10参与2009年中国云计算大会纪念
日期:2009-06-05 10:02:28ITPUB十周年纪念徽章
日期:2011-11-01 16:19:41蛋疼蛋
日期:2013-05-13 13:58:09复活蛋
日期:2013-05-15 09:53:57
13#
发表于 2005-4-27 09:46 | 只看该作者
所以我不是告诉你加一个计数器,多少W条来commit一次.
在我的设计中我就是这样做的.

使用道具 举报

回复
论坛徽章:
90
数据库板块每日发贴之星
日期:2005-04-25 01:01:202014年新春福章
日期: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:142014年世界杯参赛球队: 美国
日期:2014-06-06 14:24:30马上有对象
日期:2014-10-21 13:39:03
14#
 楼主| 发表于 2005-4-27 10:00 | 只看该作者
楼上的老大,你帮我写个看看,我来执行测试任务。。

使用道具 举报

回复
论坛徽章:
43
会员2007贡献徽章
日期:2007-09-26 18:42:10参与2009年中国云计算大会纪念
日期:2009-06-05 10:02:28ITPUB十周年纪念徽章
日期:2011-11-01 16:19:41蛋疼蛋
日期:2013-05-13 13:58:09复活蛋
日期:2013-05-15 09:53:57
15#
发表于 2005-4-27 12:22 | 只看该作者
DECLARE
  pa_num NUMBER;
  CURSOR c0 IS
    select PARTITION_NAME
    from DBA_TAB_PARTITIONS A
    where table_name = 'SM_CALLRECORD'
    AND SUBSTR(A.PARTITION_NAME, 3, 8) BETWEEN '20041002' AND '20050402'
    order by PARTITION_NAME;
  TYPE ref_cur IS REF CURSOR;
  l_cursor ref_cur;
  v_c0 C0%ROWTYPE;
  v_select_string VARCHAR2(500);
  v_update_string VARCHAR2(500);
BEGIN
  FOR v_c0 IN c0 LOOP
    v_select_string :='SELECT rowid t_rowid FROM SM_CALLRECORD PARTITION('||v_c0.PARTITION_NAME||')';
    OPEN l_cursor FOR v_select_string;
    pa_num := 1;
    FOR c1 IN l_cursor LOOP
       pa_num := pa_num+1;
       v_update_string :='UPDATE SM_CALLRECORD PARTITION('||v_c0.PARTITION_NAME||') SET CALLTIME = to_char((to_date(calltime,''yyyymmddhh24miss'')-8/24),''yyyymmddhh24miss'')';
       execute immediate v_update_string;
       IF pa_num >=100000 THEN  --issue commit per 10W records
          commit;
          pa_num := 0; --reset counter
       END IF;
    END LOOP;
    commit; --must be have more one commit command
  END LOOP;
END;

使用道具 举报

回复
论坛徽章:
90
数据库板块每日发贴之星
日期:2005-04-25 01:01:202014年新春福章
日期: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:142014年世界杯参赛球队: 美国
日期:2014-06-06 14:24:30马上有对象
日期:2014-10-21 13:39:03
16#
 楼主| 发表于 2005-4-27 13:33 | 只看该作者
FOR c1 IN l_cursor LOOP 报错。ora-06650,pls-00221,‘l_cursor ’不是过程或未定义。

使用道具 举报

回复
论坛徽章:
43
会员2007贡献徽章
日期:2007-09-26 18:42:10参与2009年中国云计算大会纪念
日期:2009-06-05 10:02:28ITPUB十周年纪念徽章
日期:2011-11-01 16:19:41蛋疼蛋
日期:2013-05-13 13:58:09复活蛋
日期:2013-05-15 09:53:57
17#
发表于 2005-4-27 14:09 | 只看该作者
对不起,REF CURSOR不能这样用,请试试下面这个
DECLARE
  pa_num NUMBER;
  CURSOR c0 IS
    select PARTITION_NAME
    from DBA_TAB_PARTITIONS A
    where table_name = 'SM_CALLRECORD'
    AND SUBSTR(A.PARTITION_NAME, 3, 8) BETWEEN '20041002' AND '20050402'
    order by PARTITION_NAME;
  CURSOR c1(v_part VARCHAR2) IS
    SELECT rowid t_rowid FROM SM_CALLRECORD PARTITION(v_part);
  v_c0 C0%ROWTYPE;
BEGIN
  FOR v_c0 IN c0 LOOP
    FOR v_c1 IN C1(v_c0.partition_name) LOOP
       UPDATE SM_CALLRECORD SET CALLTIME = to_char((to_date(calltime,'yyyymmddhh24miss')-8/24),'yyyymmddhh24miss')
       WHERE rowid = v_c1.t_rowid;
       IF pa_num >=100000 THEN  --issue commit per 10W records
          commit;
          pa_num := 0;
       END IF;
    END LOOP;
    commit; --must be have more one commit command
  END LOOP;
END;

使用道具 举报

回复
论坛徽章:
90
数据库板块每日发贴之星
日期:2005-04-25 01:01:202014年新春福章
日期: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:142014年世界杯参赛球队: 美国
日期:2014-06-06 14:24:30马上有对象
日期:2014-10-21 13:39:03
18#
 楼主| 发表于 2005-4-27 14:28 | 只看该作者
这句话 CURSOR c1(v_part VARCHAR2) IS
SELECT rowid t_rowid FROM SM_CALLRECORD PARTITION(v_part);
报错,分区不存在,可能不能这样写。

使用道具 举报

回复
论坛徽章:
90
数据库板块每日发贴之星
日期:2005-04-25 01:01:202014年新春福章
日期: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:142014年世界杯参赛球队: 美国
日期:2014-06-06 14:24:30马上有对象
日期:2014-10-21 13:39:03
19#
 楼主| 发表于 2005-4-27 14:43 | 只看该作者
我直接把语句更改如下测试性能:
[php]
DECLARE
  pa_num NUMBER;
  v_part DBA_TAB_PARTITIONS.PARTITION_NAME%TYPE;
  CURSOR c0 IS
    select PARTITION_NAME
      from DBA_TAB_PARTITIONS A
     where table_name = 'SM_CALLRECORD'
       AND SUBSTR(A.PARTITION_NAME, 3, 8) = '20041002'; --只是一个分区
  CURSOR c1 IS SELECT rowid t_rowid FROM SM_CALLRECORD PARTITION(P_20041002); --直接把这个分区写出来,不用参数传递,呵呵,不会写啊。
  v_c0 C0%ROWTYPE;
BEGIN
  FOR v_c0 IN c0 LOOP
    FOR v_c1 IN C1 LOOP
      pa_num := 1;
      UPDATE SM_CALLRECORD
         SET CALLTIME = to_char((to_date(calltime, 'yyyymmddhh24miss') -
                                8 / 24),
                                'yyyymmddhh24miss')
       WHERE rowid = v_c1.t_rowid;
      pa_num := pa_num + 1;
      IF pa_num >= 100000 THEN
        --issue commit per 10W records
        commit;
        pa_num := 1;
      END IF;
    END LOOP;
    commit; --must be have more one commit command
  END LOOP;
END;
[/php]
执行后在oem里面一看,喔,需要时间45分钟以上。会滚段每10w增加8M左右。

使用道具 举报

回复
论坛徽章:
43
会员2007贡献徽章
日期:2007-09-26 18:42:10参与2009年中国云计算大会纪念
日期:2009-06-05 10:02:28ITPUB十周年纪念徽章
日期:2011-11-01 16:19:41蛋疼蛋
日期:2013-05-13 13:58:09复活蛋
日期:2013-05-15 09:53:57
20#
发表于 2005-4-27 14:59 | 只看该作者
如果你只用一个分区的话你要将第一层的loop去掉,因为你不去掉才会花了你45minutes.
DECLARE
  pa_num NUMBER;
  v_part DBA_TAB_PARTITIONS.PARTITION_NAME%TYPE;
  CURSOR c0 IS
    select PARTITION_NAME
      from DBA_TAB_PARTITIONS A
     where table_name = 'SM_CALLRECORD'
       AND SUBSTR(A.PARTITION_NAME, 3, 8) = '20041002'; --只是一个分区
  CURSOR c1 IS SELECT rowid t_rowid FROM SM_CALLRECORD PARTITION(P_20041002); --直接把这个分区写出来,不用参数传递,呵呵,不会写啊。
  v_c0 C0%ROWTYPE;
BEGIN
  --FOR v_c0 IN c0 LOOP
    FOR v_c1 IN C1 LOOP
      pa_num := 1;
      UPDATE SM_CALLRECORD
         SET CALLTIME = to_char((to_date(calltime, 'yyyymmddhh24miss') -
                                8 / 24),
                                'yyyymmddhh24miss')
       WHERE rowid = v_c1.t_rowid;
      pa_num := pa_num + 1;
      IF pa_num >= 100000 THEN
        --issue commit per 10W records
        commit;
        pa_num := 1;
      END IF;
    END LOOP;
    commit; --must be have more one commit command
  --END LOOP;
END;

使用道具 举报

回复

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

本版积分规则 发表回复

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