tiancheng_2011
作者tiancheng_2011·2012-03-26 18:06
数据库管理员·北京华胜天成

存储过程实例3

字数 5695阅读 843评论 0赞 0
在存储过程中,假设我update100W条数据,可以批量提交么?如果可以那么每次批量提交的量可以是变量么?

DROP PROCEDURE UPDATE_DATA_INBATCH @
CREATE PROCEDURE UPDATE_DATA_INBATCH (
IN IN_DATE CHAR(8)
)
LANGUAGE SQL
MODIFIES SQL DATA
BEGIN
        --定义SQLCA变量,用于异常处理和获取上一SQL影响数据量
  DECLARE SQLSTATE CHAR(5) DEFAULT '00000';
  DECLARE errorLabel CHAR(32) DEFAULT '';
  DECLARE ROW_CNT INT DEFAULT 0;
  


  -- 异常处理
  DECLARE EXIT HANDLER FOR SQLEXCEPTION
    SIGNAL SQLSTATE value SQLSTATE SET MESSAGE_TEXT = errorLabel;
  --数据删除循环
  REPEAT
   
         UPDATE(SELECT * FROM TRNFLW WHERE TRAN_DATE<IN_DATE FETCH FIRST 50000 ROWS ONLY) SET TRAN_DATE=current date;
         --获取DELETE语句的影响数据量,用于循环判断是否删除完毕
         GET DIAGNOSTICS ROW_CNT=ROW_COUNT;
         --提交,将50000数据量落实到数据库,并释放50000个锁
         COMMIT;
  UNTIL ROW_CNT<>50000
  END REPEAT;
END @


曾经帮别人写的过程,应该对你有用:
该过程的作用是 更新表的字段 ISOVER的值为 0,1

CREATE PROCEDURE TAUTOMONITOR.DS_UPDATE_WATER_FAC_DAY_DATA_ISOVER  ( )
LANGUAGE SQL
begin

    myloop:loop
      when exists(select 1 from T_WATER_FAC_DAY_DATA where ISOVER not in('0','1')) --如果没有要更新的数据就退出循环
      then
          --每次更新10万条数据,并提交
           UPDATE (select ISOVER,AVGSTRENGTH,STANDARDVALUE from T_WATER_FAC_DAY_DATA where ISOVER not in('0','1') fetch first 100000 rows only) a
           SET a.ISOVER=(CASE WHEN a.AVGSTRENGTH>a.STANDARDVALUE THEN '1' ELSE '0' END );
   
           commit;
      else
           leave myloop;
      end ;
    end myloop;
end

比如有一张table1,有A,B,C三个字段。取B字段时如果为空的话就以一位空格代替,不为空的话就取实际值。语句怎么写呢??

select A,case when B is null then ' ' else B end as B,C from table1
select A,COALESCE(B,' '),C from table1
select A,NVL(B,' '),C from table1
COALESCE可以用来评价NULL.可以取到一系列表达式中的第一个非NULL值.
                       .-------------.
                        V             |
>>-COALESCE-(expression---,expression-+-)----------------------><

同一个存储过程同样的条件第一次执行和短时间内的第二次执行速度会差很多,我想可能是因为缓冲池缓存了数据的原因。
请问有什么命令可以清除缓冲池数据缓存吗?
我的目的是为了调试存储过程,查看前后对比,当然是在都没有缓存的情况下才更准确。
各位都用什么方法做这个事情呢?

new fixpack (v91fp5+, v95fp2+) there's "db2pdcfg -db <dbname> -flushbp"

FLUSH PACKAGE CACHE statement 对动态sql奏效   flushbp 是刷新脏页啊,为什么不用db2自己提供的db2batch基准测试工具呢?他可以保证db2具有相同的环境。或者针对如此存储过程,为什么不让参数动态呢?一个思路,单纯测试一个存储过程,同样参数是没什么意义的,缓存总会奏效。
lz的测试是只读的,清脏页没用。
在活动库/生产库上这个没解,也不会让这么干。测试库的话,deactivate就行了。

DB2与Oracle优化器的具体差异????
用db2的时间不长
1、感觉db2  在分析sql(等价转换sql的功能还是比oracle强大)
2、oracle10g 前,没有  多列 信息统计,这一点db2 是有的,oracle 11g 才有这个功能
3、oracle hint 使用比较方便,比db2 profile 方便多了,可能是db2 profile 用的人少吧
这说明:db2的优化器 对自己很有信心
        oracle 初期的优化器比较弱,比如说oracle8 以前的
4、db2 优化器 分等级 DFT_QUERYOPT,可以有选择  ,oracle 这方面没有
5、因为是人为的优化器  所有都不够完美,总会出现 不能正确认识 执行计划的时候
而不能正确认识执行计划的时候
    oracle 在这方面 处理起来比 db2 有优势,比如说hint,11g sql计划管理
    db2 这方面能做的就很少,而且比较复杂
6、db2优化器会考虑约束的情况,oracle不会考虑这一点,这个在多表查询的时候比较有用
7.oracle的进步比较明显,db2 似乎创新不足
我对db2 了解还不够,高手补充一下

ORACLE:提供的hint提示对于一些比复杂非常高的sql有很好的帮助,使用起来也比较简便,但是需要DBA有相当高的优化技巧,否则建议中规中矩的做比较好。
db2:对于一般复杂的SQL,调整下调优级别,采用db2advis的建议问题就不大了。对于高等复杂的SQL,也有类似hint提示的方法可以提供,比较底层的做法是xml格式的提示加到sql中来,这个写法较oracle的hint提示稍微复杂些,对于痛恨xml的兄弟们来说就很讨厌了

优化流程基本一样,只不过ORACLE有更多的手段去影响执行计划,比如HINT、存储大纲、SQL基线。另外ORACLE的EXPLAIN更加直观。
DB2跟ORACLE中SQL关键是采用HASH JOIN,当然如果存在SORT的话还是采用MERGE JOIN。
优化的基本思路是先收集统计信息,然后看执行计划,如果执行计划还是不理想的话(DB2一般都仓库,采用HASH。可以看下连接谓词两边数据类型是否一致,包括精度。当然也可以用ADVISOR看看。ORACLE你可以强制采用某种连接方式,采用HINT,当然是你熟悉关联表的数据分布的情况下。也可以在分析表的时候做柱状图。优化器默认数据是均匀分布的,这对于存在严重数据SKEW的情况非常有效,当然前提是采用索引扫描)。
另外ORACLE不建议关联时候存在太多表和视图(视图没有统计信息),似乎是优化器不够智能,EXPLAIN中的信息会不正确,这个时候需要分拆一下。另外还有AWR等等手段去分析系统问题。
不管是DB2还是ORACLE要尽量缩小数据查询范围,在WHERE谓词中进行限定。

请教pagesize设置成多大比较合适?


v95里面large pagesize没有有255行的限制~~
page size取决于时间/空间的交换定律
节省了空间,在大量数据查询时需要多个I/O,则消耗时间
否则节约了时间,但是有可能会浪费空间……

具体怎样决定取决于你们的系统,特别是在V9.5之后,行数限制远远扩大,pagesize的大小关键还是系统的类型
之前的表空间有255行的限制,如果你选取的页大小比较大,而数据行长度比较小,那么当达到255后,会浪费其余未使用的空间。

而现在9.1之后没有了这个255的限制,因为是large tablesace.因此不会存在浪费空间的问题,但是表空间的也大小会影响索引的级别数和缓冲池的利用率。如果也太大,而行比较小,那么会读取很多多余的数据,浪费缓冲池.
after v91, db2 uses large rowid- 2 bytes for slotid(7FFF), before v91, rowid is only 1 byes for slot id(255), so number of rows does matter with the pagesize, but constrained by rowid.

DB2的备份文件的前16个字节应该是字符串SQLUBRMEDHEAD加一个空格和两个00
问题如下:

想做REORG --> RUNSTATS --> REBIND,但是时间很长,没有这么大的时间窗口。请问有没有什么好的方法,在RUNSTATS和REORG的时候带什么参数????

牛博士的书上建议,如果不是7*24,可以采用 export --->带Statistics选项的load replace来操作。说不但做了表和索引碎片整理还做了统计信息更新,而且时间比常规的方式大大缩短。 但是这样的缺点是必须停掉应用一段时间,即不能7*24
我是先export成ixf
然后alter table empty
最后load replace Statistics yes and indexes all nonrecoverable
offline reorg就是创建一个shadow copy,然后在shadow copy里面把一行一行数据码放整齐,然后替换原来的表,就好了
online的相对麻烦一点,每次根据索引(如果有cluster index)锁定若干行,然后把他们码放好,提交操作,然后锁其他的~~~这期间表可以被读写访问。online reorg的锁不会被timeout,而且是低优先权事务

export +load 一样需要额外空间存放导出来的文件,
export其实就是不断fetch的过程,fetch单线程的,
而且需要把内部的记录格式转换为标准的SQLDA格式,这非常消耗CPU。
对于大表来讲,export可能需要很长时间。。。。
而reorg 的build和replace过程都是直接页复制,应该效率快很多(pagesize越大越明显)。
而index rebuild过程是load也需要做的,所以我觉得reorg会比export+load效率高。





如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

0

添加新评论0 条评论

Ctrl+Enter 发表

作者其他文章

  • 将表标记为无效
    评论 0 · 赞 0
  • 记录九
    评论 0 · 赞 0
  • 存储过程创建和查询
    评论 0 · 赞 0
  • 问题总结续八
    评论 0 · 赞 0
  • 操作系统内存和数据库内存
    评论 0 · 赞 0
  • 相关文章

    相关问题

    相关资料

    X社区推广