Dreamhost | Previous | 2009-07-01 Wed | Next |

2009-07-01 Wed

05:26 金庸小说中的美女与佳人 (10203 Bytes) » DBA notes

作者:Fenng 发布在 dbanotes.net. BLOG 墙外订阅数量,点击则可进行订阅

金庸小说中的美女? 这可能是一个比较老的话题了。如果"到Google上百度一下",能找到不下百万条的记录结果。之所以会有这么多结果,可能和每个读者心目中的理想美女标准不一吧。

尽管是个老掉牙的话题,考虑到公司(注:阿里巴巴集团)崇尚武侠文化,所以唠叨几句,再做点普及可能也不算过时。有些人物形象,比如黄蓉小龙女等已是深入人心,再此略过不表。再者,美与不美是相对的,比如《《天龙八部》中的怪人包不同就觉得自己女儿包不靓最美嘛。

小昭

小昭是金庸最喜欢的女性人物。其容貌"双目湛湛有神,修眉端鼻,颊边微现梨涡,直是秀美无伦",我们又从文中得知小昭生父韩千叶系中土人士,其母黛绮丝人家还是波斯的圣女,居然是个混血儿,考虑到遗传因素,所以美貌自不待言,比一般的美女更美也是情理之中的事情。

小昭武功不弱,聪明伶俐,通音律,且精通奇门八卦之术,绿柳庄外曾救得群雄性命,从这一点来看,人家是个完美的知识女性,用现在的话说,那叫知性美女。小昭对爱情忠诚,富有牺牲精神,最后为了张无忌而痛心远走波斯,这是颇为读者神伤的一段。

小昭恐怕也是金庸先生心目中的理想女性的化身,另外一个和她人物形象有点重叠的是双儿,当然,双儿更多了一点温柔(所以能得圆满?)。类似的女性人物形象在金庸作品中出现两次,可见作者心目中的理想美女亦相去不远。暗自揣测,这两个人物形象或许是参照金庸第三任妻子林乐怡而写的,当然这个一家之言,还有待考证。

小昭堪称金庸小说中的绝顶佳人。不知道是否有武侠小说迷按照这个标准寻找意中人的,哈哈。

郭襄

《神雕侠侣》中的郭襄,是金庸所有小说中最具亲和力的人物,"潇洒如诗",也是金庸所有小说中最闪亮的配角人物,一见难忘,所以让何足道与张三丰"为君沉吟"。

痴情者如郭襄者,少见又少见。"天涯思君不敢忘",一遇杨过误终身,爱慕杨过而不可得,杨过喜欢的那句话"世间不如意者,十居七八"倒应在了她身上。不是有人说了么,"得不到的东西最美好",如果郭襄真的能和杨过在一起,反而未必那么圆满,"得不到的东西最美好",但愿如此。郭襄这样的女子当今社会怕是没有了----都直接当小三去了。顺便说一下,郭襄的徒孙周芷若是金庸小说中相当令人生厌的人物,从某种角度上看,不亚于康敏。

王语嫣家族女性

看来遗传因素决定了一切,王语嫣一家的女性貌似都貌美得不得了。好像只有他妈王夫人稍微差了一点,估计隔代遗传的因素作怪吧。容貌归容貌,这个家族的人物性格并不讨人喜欢。

在最近新修版的《天龙八部》中,王语嫣的人物形象较之先前有了较大改变,最后热衷寻求长生不老之术,幻想青春永驻。个人认为,这是金庸小说中体现的西方神话形象那西塞斯(Narcissus)的女性版。以王语嫣为代表的女性可能是美女,但非常无趣。如果段誉娶了这样的媳妇,绝对糟糕透顶。王语嫣可算上美女,但无论如何不是佳人。

冯蘅

这是一个必须一提的人物。也是个相对比较陌生的名字,冯蘅是谁? 黄蓉她妈,黄药师的妻子。

仅仅通过其他人物的口中就已经能够得知绝代风貌,且不说黄药师如此另类人物被其折服,其过目不忘之能也当世少有,令人心驰神往,原来美貌与智慧是可以并存的。考虑到黄蓉同学多少只是他母亲的影子,加上大家太熟悉这个角色,不复赘言。

新修版中居然情节更改为黄药师因为弟子们说闲话而斗气娶了冯蘅,实在是大煞风景。这个变动相当的蛇足。

程灵素

金庸先生书中女主人公绝大多数都算美女,但程灵素除外。"头发稀疏,肌肤枯黄,脸有菜色",如果分析一下,可能是这个古代化学专家整天接触药石之故,如果放到现在,人家就是个化学兼医学双料女博士,外表不美,心灵美,这也顶顶重要。其实内在美重要,还是外在美重要,不同的历史时期人们的价值取向也是不同的,也或许有人喜欢程灵素也说不定。

程灵素最后为胡斐牺牲,不由得让人埋怨作者下笔残酷,如果武侠小说允许假设,那么胡斐娶了程灵素是不会让人感到意外的。

香香公主

香香公主之美,美到不够真实,而其不谙世事,也似乎不是凡间之人。激战双方的兵士见到她居然"便似中邪昏迷一般,人人都呆住了...无数长矛都掉下地来,弓箭手的弓矢也收了回来...人人神色和平,收刀入鞘",如果在今天,维护世界和平旧靠她了:) 塑造这个小说人物的时候恐怕也多少投射了一些西方经典美女海伦的有关因素在里面吧。

金庸早期小说人物形象多半缺乏立体感,香香公主也是如此,甚至在同一部小说中,还不如霍青桐更能赢得人好感。

陈圆圆

当然,香香公主再美,可能还敌不过陈圆圆,陈圆圆有多美,无法形容(所以不可能留下'西施捧心'之类的形象给世间人)!因为无法形容,所以作者描写陈圆圆多用映衬笔法,纵观全部金庸小说,这是相当精彩的地方,丝毫不亚于纯文学作品。在《碧血剑》中曾有一幕,写到闯王帐下群雄见到当世第一美人莫不疯狂,甚至袁承志这样的人见到她也是心中荡漾。多年之后,韦小宝第一次见到陈圆圆时虽已韶华不再,但风韵不减当年,仍禁不住"张大了口竟然合不拢来...";再说,女儿阿珂都把韦小宝震撼得"我要死了",更别说人家老娘了。

貌美不是好事情,汉族文化的传统思维是红颜祸水,其实"冲冠一怒为红颜"关卿何事? 不过是政治家争权夺势的借口罢了。陈圆圆终其一生,何其不幸也。在吴三桂和李自成这两个枭雄中间注定得不到得不到幸福,更为天下人唾骂,这也是造化使然。金庸小说中的陈圆圆,是不折不扣的悲剧形象,其后半生青灯古佛,心怀天下苍生,那是万分难得的菩萨心肠了。

最后多说一笔,如果陈圆圆不那么美貌的话,恐怕中国历史要改写吧? 当然,这个有点扯远了,否则,该有同学说"丘处机不该路过牛家村"这回事儿了。

--EOF--

金庸小说本来是网友写烂了的题材。这是给公司内刊投稿的文章(美女题材在家里是个禁忌,我这也是冒着被老婆揍的风险)。算是重温了一下渐行渐远的武侠文化吧。


相关文章|Related Articles

评论数(2)|添加评论 | 最近作者还说了什么? Follow Fenng@Twitter
本文网址:

DBA Notes 理念: 用简约的技术取得最大的收益...

00:10 DBA日记 第二部 (32) 外来的和尚好念经 5月1日 上网聊天 (37284 Bytes) » DBA日记

1.1.1. 5月1日 在家聊天

今天是51日,劳动节7天长假的第一天。我自从几年前5.1节的时候和老婆去了趟三亚,就决定再也不长假出游了。所以长假期间我一般选择在家休息,每个长假的最后2天才安排在深圳周边玩玩。由于昨晚Richard要对系统的IO做一次小的调整,最近一直担惊受怕的老万十分紧张,怕调整后系统出现严重的问题,所以他希望我今天能帮他盯一天系统。

选择昨天晚上选择优化实施实际上不是一个好主意,今天是5.1长假的第一天,即将入夏的时节,又赶上放假,正是白家电促销的好日子。今天全国的白家电销量应该是一个小高峰,根据业务部门的测算,老万他们这套系统的负载肯定高于430日。选择昨天晚上动手优化的风险十分高,一旦今天出现问题,那么Richard将面临的形势将十分严峻。我一直不理解Richard这么做的真实意图,也许是老外并不知道5.1这个日子的特殊性,也许真的是Richard对昨天的动作十分有把握。不过无论如何,如果是我,绝对不敢选择在CPU这么高的时候单独去优化IO,也许这回我真的遇到了高人了,如果真的是这样,那就太好了,我也可以好好和他切磋切磋。

登录到VPN后,感觉今天系统的状况出奇的好,现在已经是上午的10点左右了,按理说应该是一天中业务量比较大的时段,CPU空闲还有15%左右,IO系统的表现和很好,AVWAIT基本少接近于0AVSERV20左右。难道是Richard的优化起了作用?我马上做了一个STATSPACK的采样,并且和9点的采样生成了一份报告。

由于Statspack的采样很久没有清理了,所以报告生成的很慢。在报告生成的时候,我看了看QQ的在线用户,老万的QQ状态是“忙碌”。我于是发信息过去给老万打了个招呼:“万科,早”。

老万回信息说:“老白,今天的情况异常的好,我看了个把小时了,active的会话数量一直低于80CPU使用率也不高。看样子Richard昨天的优化效果十分明显,别看这老外五大三粗的像个土匪,不过还是有两下子的。”

我说:“按照理论来说,Richard所做的优化操作并不是很合理,不应该会有这样的效果。万科,有没有可能今天的业务量不大?”

老万说:“这一点我也疑问过,所以刚才我给国内几个工贸公司都打了电话,他们反馈回来的信息是今天的产品销售量比昨天普遍略高5-10%。”

这太不正常了,难道昨天晚上Richard还做了什么我不知道的调整?这个时候Statspack报告已经生成完毕了,我马上打开了报告

Load Profile

~~~~~~~~~~~~                            Per Second       Per Transaction

                                   ---------------       ---------------

                  Redo size:            184,507.91              6,333.90

              Logical reads:            133,335.76              4,577.23

              Block changes:              1,053.27                 36.16

             Physical reads:              2,535.17                 87.03

            Physical writes:                127.19                  4.37

                 User calls:              3,996.10                137.18

                     Parses:                568.89                 19.53

                Hard parses:                 49.98                  1.72

                      Sorts:                 26.44                  0.91

                     Logons:                  0.38                  0.01

                   Executes:                772.16                 26.51

               Transactions:                 29.13

 

  % Blocks changed per Read:    0.79    Recursive Call %:                21.92

 Rollback per transaction %:    0.51       Rows per Sort:              2971.01

 

Instance Efficiency Percentages (Target 100%)

            Buffer Nowait %:   99.98       Redo NoWait %:              100.00

            Buffer  Hit   %:   98.12    In-memory Sort %:               99.99

            Library Hit   %:   98.26        Soft Parse %:               91.22

         Execute to Parse %:   26.32         Latch Hit %:               98.12

Parse CPU to Parse Elapsd %:    8.08     % Non-Parse CPU:               93.36

从单块读的响应时间来看,确实今天的IO系统性能有了十分明显的提升:

                                                                   Avg

                                                     Total Wait   wait    Waits

Event                               Waits   Timeouts   Time (s)   (ms)     /txn

---------------------------- ------------ ---------- ---------- ------ --------

db file sequential read         6,508,594          0     41,645      6     62.0

latch free                        983,166          0     12,239     12      9.4

db file scattered read            194,469          0      2,674     14      1.9

我算了一下平均事务响应时间,是732毫秒,比前一阵子的3秒左右有了很大的提升。这真是太不可思议了。我让老万立即对今天的WORK_ORDER表进行一个统计,看看业务量和昨天对比相差多大。老万统计了一下后告诉我从9点到10点的工单量来看,今天的的工单量比430号少15%左右,看来有些工贸公司的量还是略有下降。看样子今天虽然销售量比较大,不过安排送货安装的并不多,也许商场的送货人员也放假了,要等4号才开始工作。不过从另外一个方面考虑,15%的业务量下降也不应该有这么大的效果啊。

我认真看了看Load Profile,突然发现今天报告里的平均事务数量是每秒29个,而前几天是57,也就是说今天系统的平均事务量是30号的一半。从刚才老万他们对工单表的统计来看,不应该有这么大的差异,是什么地方出现了问题呢?

“老万,今天工贸公司放不放假?”,我突然问老万。

“放啊,今天除了值班的都放假,这有什么关系?”,老万疑惑的问我。

我恍然大悟了:“老万,你别忘了,你这个系统除了业务人员用以外,工贸公司的1500个管理岗位也在用啊,而且这1500个管理岗位消耗的系统资源是相当的大,他们总是在做一些统计和分析。今天的现象只是一个暂时性的,等长假结束了,你就会看到情况并不这么乐观。”

老万一听就笑了:“我还真忘了这茬了,这帮大爷经常自己写SQL去做统计,我们每天的主要工作就是杀那帮家伙的会话”。

如果工贸公司的1500个终端没有开的话,系统负载起码少了30%以上,看样子老万是空欢喜了一场,不过我的心情却无比的好,看来我的判断并没有错,仅仅靠Richard的那几招,想要解决问题还是不可能的。

看看时间,已经是中午12点了,我说:“万科,今天下午就没必要盯着了,估计长假前三天都不会有什么问题,4号后可能会有一些工贸公司的人加班,压力会大一些,不过也不会有大的问题,关键是8号。”

老万想了想说:“是啊,看样子这几天也不会有太大的负载,5.1节促销的效果也没有想象的那么明显,又被业务部门忽悠了一把,还增长20%的业务量,都是拍脑袋拍出来的,明显不是那回事。老白,你这几天也没必要盯着了,不过8号你一定帮我盯紧了,8号我预感会发生点什么。”

中午睡了个午觉,一觉醒来已经是3点半了。VPN连过去看了看,系统负载依然很小。看样子这几天确实都不需要怎么关心了。想想也对,以前就出过几次问题,当时是把内网工贸公司的应用停了来应急的,每次都是立竿见影的,一停内网应用,系统马上就缓过来了。

刚上网就发现马工也在网上,我问他在做什么,他说下午他值班,万科自己回家了,不过还是让他盯到5点。小马自己一个人在青岛,也没什么朋友,加班挣点加班费还是挺不错的。正和小马聊着,Richard通过MSN发了一条消息:“Hi,老兄,今天系统十分完美”。

Richard 用了perfect,足以表明他现在的心情。Richard认为今天的性能情况和他昨天的动作有很大关系。我想给他泼泼冷水,不过费了半天脑子,也没有想好怎么说。“5.1长假”这个词汇我用了好几个英文单词去描述,他还是没有听明白什么意思。后来我只好解释说今天就类似他们西方的圣诞新年假期一样,很多业务人员都休息去了,所以今天的系统负载只是平时的60-70%。总算,Richard听明白了我要表达的意思,不过他还是认为优化获得了阶段性的成果。

我想我也很难说服他,老外都是一根筋,你很难去说服他。只有到58日,系统真正体现出了压力,才能让他明白老万他们这个项目的优化并不像他想象的那么简单。以今天的业务量,CPU资源肯定会出现瓶颈

2009-06-30 Tue

20:09 Oracle 10g LOGMNR挖掘日志很方便 (8724 Bytes) » Oracle Life

©作者:eygle 发布在 eygle.com

Oracle 10g可以使用LOGMNR在线分析和挖掘日志,使用当前在线的数据字典,非常方便。

首先执行一些DDL或DML操作:
SQL> connect eygle/eygle
Connected.

SQL> alter system switch logfile;

System altered.

SQL> create table eygle as select * from dba_users;

Table created.

SQL> set autotrace on
SQL> select count(*) from eygle;

  COUNT(*)
----------
        19


Execution Plan
----------------------------------------------------------
Plan hash value: 3602634261

--------------------------------------------------------------------
| Id  | Operation          | Name  | Rows  | Cost (%CPU)| Time     |
--------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |     1 |     3   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |       |     1 |            |          |
|   2 |   TABLE ACCESS FULL| EYGLE |    19 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement


Statistics
----------------------------------------------------------
          5  recursive calls
          0  db block gets
          7  consistent gets
          5  physical reads
          0  redo size
        411  bytes sent via SQL*Net to client
        400  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
然后可以执行LOGMNR解析工作:
SQL> connect / as sysdba
Connected.
SQL> select * from v$log where status='CURRENT';

    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIME
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ------------
         2          1        100   52428800          1 NO  CURRENT               12729697 01-JUL-09

SQL> SELECT MEMBER from v$logfile where group#=2;

MEMBER
------------------------------------------------------------------------------------------------------------------------
/opt/oracle/oradata/mmstest/redo02.log

SQL> exec dbms_logmnr.add_logfile('/opt/oracle/oradata/mmstest/redo02.log',dbms_logmnr.new);

PL/SQL procedure successfully completed.

SQL> exec dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog);

PL/SQL procedure successfully completed.

SQL> select count(*) from v$logmnr_contents;

  COUNT(*)
----------
       136
SQL> select sql_redo from v$logmnr_contents;

SQL_REDO
------------------------------------------------------------------------------------------------------------------------
set transaction read write;
insert into "SYS"."OBJ$"("OBJ#","DATAOBJ#","OWNER#","NAME","NAMESPACE","SUBNAME","TYPE#","CTIME","MTIME","STIME","STATUS
","REMOTEOWNER","LINKNAME","FLAGS","OID$","SPARE1","SPARE2","SPARE3","SPARE4","SPARE5","SPARE6") values ('25847','25847'
,'31','EYGLE','1',NULL,'2',TO_DATE('01-JUL-09', 'DD-MON-RR'),TO_DATE('01-JUL-09', 'DD-MON-RR'),TO_DATE('01-JUL-09', 'DD-
MON-RR'),'1',NULL,NULL,'0',NULL,'6','1',NULL,NULL,NULL,NULL);

set transaction read write;
update "SYS"."CON$" set "CON#" = '10823' where "CON#" = '10822' and ROWID = 'AAAAAcAABAAAACqAAM';

commit;
set transaction read write;

SQL_REDO
------------------------------------------------------------------------------------------------------------------------
update "SYS"."CON$" set "CON#" = '10824' where "CON#" = '10823' and ROWID = 'AAAAAcAABAAAACqAAM';

commit;
set transaction read write;
update "SYS"."CON$" set "CON#" = '10825' where "CON#" = '10824' and ROWID = 'AAAAAcAABAAAACqAAM';

commit;
set transaction read write;
update "SYS"."CON$" set "CON#" = '10826' where "CON#" = '10825' and ROWID = 'AAAAAcAABAAAACqAAM';

commit;


set transaction read write;
update "SYS"."CON$" set "CON#" = '10827' where "CON#" = '10826' and ROWID = 'AAAAAcAABAAAACqAAM';

commit;
set transaction read write;
update "SYS"."CON$" set "CON#" = '10828' where "CON#" = '10827' and ROWID = 'AAAAAcAABAAAACqAAM';

commit;
set transaction read write;
update "SYS"."CON$" set "CON#" = '10829' where "CON#" = '10828' and ROWID = 'AAAAAcAABAAAACqAAM';

commit;
create table eygle as select * from dba_users;
set transaction read write;


Unsupported
update "SYS"."TSQ$" set "TS#" = '0', "GRANTOR#" = '43080', "BLOCKS" = '0', "MAXBLOCKS" = '0', "PRIV1" = '0', "PRIV2" = '
0' where "TS#" = '0' and "GRANTOR#" = '43072' and "BLOCKS" = '0' and "MAXBLOCKS" = '0' and "PRIV1" = '0' and "PRIV2" = '
0' and ROWID = 'AAAAAKAABAAAABbAAF';

commit;
set transaction read write;
SQL> exec dbms_logmnr.end_logmnr

PL/SQL procedure successfully completed.
很多时候拿LOGMNR来追踪一些误操作是很有效的方式,甚至在自己定制的数据同步中,LOGMNR也大有可为。






相关文章|Related Articles

评论数量(0)|Add Comments

本文网址:

09:09 分区表用哪个级别的统计信息? (6885 Bytes) » AnySQL.net

    这几天有几个分区表上的SQL执行计划不正常, 感觉上不应当, 已经设置了几个容易引起优化器选错执行计划的参数了.

ALTER SYSTEM SET OPTIMIZER_DYNAMIC_SAMPLING=0;
ALTER SYSTEM SET "_optim_peek_user_binds"=false;

    按照现行的表分析原则, 只统计了表的全局索引, 不统计表分区上的索引, 因为分区会有增减操作, 不是每个分区都有数据, 也没有定下来要经常分析表, 而是分析后如果不出问题就不再分析. 现在SQL走错了, 可能的原因有什么呢? 重新分析一下不行, 看了一下执行计划, 发现全表扫描的COST值很底, 估计是用了分区上的统计信息了, 于是手动将全局的统计信息复制到每一个分区上得以解决.

    为了得到原因, 回顾了一下当时的SQL, 发现有一个特征, 就是出问题的SQL都能定位到某个分区或某些分区, 今天就模拟了一下情况, 先只有全局统计信息. 首先用分区列范围查询, 去试了一下, 发现用的是分区级的统计信息.

SQL> select * from database_perf_statistics
  2  where day > sysdate - 100 and day < sysdate + 300;

----------------------------------------------------------------
| Id  | Operation                 | Cost (%CPU)| Pstart| Pstop |
----------------------------------------------------------------
|   0 | SELECT STATEMENT          |     3   (0)|       |       |
|*  1 |  FILTER                   |            |       |       |
|   2 |   PARTITION RANGE ITERATOR|     3   (0)|   KEY |   KEY |
|*  3 |    TABLE ACCESS FULL      |     3   (0)|   KEY |   KEY |
----------------------------------------------------------------

    然后全表扫描, 涉及所有的分区时, 用的是全局的统计信息.

SQL> select * from database_perf_statistics;
             
----------------------------------------------------------
| Id  | Operation           | Cost (%CPU)| Pstart| Pstop |
----------------------------------------------------------
|   0 | SELECT STATEMENT    |  2196   (1)|       |       |
|   1 |  PARTITION RANGE ALL|  2196   (1)|     1 |     4 |
|   2 |   TABLE ACCESS FULL |  2196   (1)|     1 |     4 |
----------------------------------------------------------

    再测试一个开包的查询条件, 发现用的也是分区的统计信息.

SQL> select * from database_perf_statistics where day > sysdate - 100;

---------------------------------------------------------------
| Id  | Operation                | Cost (%CPU)| Pstart| Pstop |
---------------------------------------------------------------
|   0 | SELECT STATEMENT         |     3   (0)|       |       |
|   1 |  PARTITION RANGE ITERATOR|     3   (0)|   KEY |     4 |
|*  2 |   TABLE ACCESS FULL      |     3   (0)|   KEY |     4 |
---------------------------------------------------------------

    重新设置了一下各分区的统计信息, 再验证一下上面的SQL的COST值, 就确定了是这个原因引起的, 需要更改一下我们的分析策略了.

Relative Posts:

06:31 恩墨科技为ChinaCache提供紧急救援服务 (3368 Bytes) » Oracle Life

©作者:eygle 发布在 eygle.com

日,恩墨科技为ChinaCahce提供了紧急数据库援助服务

ChinaCache成立于1998年,是中国领先的专业CDN服务提供商,向客户提供全方位网络内容快速分布解决方案。作为2000年就获信产部许可的 CDN服务提供商,目前ChinaCache在全国100多个大中城市拥有近500个节点,覆盖中国电信、中国网通、中国移动、中国联通、中国铁通和中国 教育科研网等各大运营商。2007年,ChinaCache北美公司的建立,使ChinaCache网络覆盖了北美及亚太地区。

ChinaCahce与恩墨科技长期以来一直保持着良好的合作与联系,最近的一次意外断电事故,使得客户的数据库系统受到了影响,在经过了数小时的排查之后,客户请求我们介入协助寻求解决方案,在经过了全面的思考和一系列的尝试之后,我们成功的帮助用户恢复了数据库服务,使得TB级数据库能够再次提供服务。

感谢用户的信赖和支持,希望我们的服务能够继续为用户创造价值!




相关文章|Related Articles

评论数量(2)|Add Comments

本文网址:

2009-06-29 Mon

23:00 对index直接rebuild的时候一定会是index fast full scan吗 (73037 Bytes) » Focus on Oracle

index直接rebuild的时候一定会是index fast full scan吗?

呵呵,当然不是,我们来看一个反例:

 

SQL> create table testindex

  2  (pvalue varchar2(1),

  3   pkey number)

  4  partition by range (pkey)

  5  (

  6  partition testindex_part_1 values less than (2)

  7  tablespace TESTTBS1,

  8  partition testindex_part_2 values less than (3)

  9  tablespace TESTTBS2

 10  )

 11  enable row movement;

 

Table created

 

SQL> insert into testindex values('a',1);

 

1 row inserted

 

SQL> insert into testindex values('b',1);

 

1 row inserted

 

SQL> insert into testindex values('c',2);

 

1 row inserted

 

SQL> insert into testindex values('d',2);

 

1 row inserted

 

SQL> commit;

 

Commit complete

 

SQL> create index idx_testindex_pvalue on testindex(pvalue);

 

Index created

 

我把pvalue='a'的那条记录的pkey1改为2,这时候因为上述分区在不同的表空间下,所以索引idx_testindex_pvalue中对应于键值为'a'global rowid一定会变。

 

好了,我们来验证一下:

未改之前:

row#0[8017] flag: -----, lock: 0

col 0; len 1; (1):  61

col 1; len 10; (10):  00 01 50 dd 21 80 07 99 00 00

row#1[8002] flag: -----, lock: 0

col 0; len 1; (1):  62

col 1; len 10; (10):  00 01 50 dd 21 80 07 99 00 01

row#2[7987] flag: -----, lock: 0

col 0; len 1; (1):  63

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 00

row#3[7972] flag: -----, lock: 0

col 0; len 1; (1):  64

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 01

 

SQL> update testindex set pkey=2 where pvalue='a';

 

1 row updated

 

SQL> commit;

 

Commit complete

 

SQL> select * from testindex;

 

PVALUE       PKEY

------ ----------

b               1

c               2

d               2

a               2

 

改过之后:

row#0[8017] flag: ---D-, lock: 2

col 0; len 1; (1):  61

col 1; len 10; (10):  00 01 50 dd 21 80 07 99 00 00

row#1[7957] flag: -----, lock: 2

col 0; len 1; (1):  61

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 02

row#2[8002] flag: -----, lock: 0

col 0; len 1; (1):  62

col 1; len 10; (10):  00 01 50 dd 21 80 07 99 00 01

row#3[7987] flag: -----, lock: 0

col 0; len 1; (1):  63

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 00

row#4[7972] flag: -----, lock: 0

col 0; len 1; (1):  64

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 01

这里我们可以从trace文件中看到索引idx_testindex_pvalue中对于键值为'a'global rowid已经由00 01 50 dd 21 80 07 99 00 00变成了00 01 50 de 22 00 11 19 00 02

 

现在我们重建上述index,再来验证将上述index设为unusable的情况下索引idx_testindex_pvalue中对应于键值为'a'global rowid是否会变?

SQL> update testindex set pkey=1 where pvalue='a';

 

1 row updated

 

SQL> commit;

 

Commit complete

 

SQL> select * from testindex;

 

PVALUE       PKEY

------ ----------

b               1

a               1

c               2

d               2

 

SQL> drop index idx_testindex_pvalue;

 

Index dropped

 

SQL> create index idx_testindex_pvalue on testindex(pvalue);

 

Index created

 

未改之前:

row#0[8017] flag: -----, lock: 0

col 0; len 1; (1):  61

col 1; len 10; (10):  00 01 50 dd 21 80 07 99 00 02

row#1[8002] flag: -----, lock: 0

col 0; len 1; (1):  62

col 1; len 10; (10):  00 01 50 dd 21 80 07 99 00 01

row#2[7987] flag: -----, lock: 0

col 0; len 1; (1):  63

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 00

row#3[7972] flag: -----, lock: 0

col 0; len 1; (1):  64

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 01

 

SQL> alter index idx_testindex_pvalue unusable;

 

Index altered

 

SQL> update testindex set pkey=2 where pvalue='a';

 

update testindex set pkey=2 where pvalue='a'

 

ORA-01502: index 'DRAS.IDX_TESTINDEX_PVALUE' or partition of such index is in unusable state

 

SQL> ALTER SESSION SET SKIP_UNUSABLE_INDEXES = TRUE;

 

Session altered

 

SQL> update testindex set pkey=2 where pvalue='a';

 

1 row updated

 

SQL> commit;

 

Commit complete

 

SQL> select * from testindex;

 

PVALUE       PKEY

------ ----------

b               1

c               2

d               2

a               2

 

改过之后:

row#0[8017] flag: -----, lock: 0

col 0; len 1; (1):  61

col 1; len 10; (10):  00 01 50 dd 21 80 07 99 00 02

row#1[8002] flag: -----, lock: 0

col 0; len 1; (1):  62

col 1; len 10; (10):  00 01 50 dd 21 80 07 99 00 01

row#2[7987] flag: -----, lock: 0

col 0; len 1; (1):  63

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 00

row#3[7972] flag: -----, lock: 0

col 0; len 1; (1):  64

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 01

可以从结果里看到,这时候当我将上述index设为unusable的情况下索引idx_testindex_pvalue中对应于键值为'a'global rowid没有变!

 

这时候如果我们rebuild online的话是能修正上述错误的,因为rebuild online走的是全表扫描。但是如果我们只是rebuild,因为rebuild走的是index fast full scan那这里oracle能正确的修正上述global rowid的错误吗?我们来验证一下:

SQL> alter index idx_testindex_pvalue rebuild;

 

Index altered

 

rebuild之后:

row#0[8017] flag: -----, lock: 0

col 0; len 1; (1):  61

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 03

row#1[8002] flag: -----, lock: 0

col 0; len 1; (1):  62

col 1; len 10; (10):  00 01 50 dd 21 80 07 99 00 01

row#2[7987] flag: -----, lock: 0

col 0; len 1; (1):  63

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 00

row#3[7972] flag: -----, lock: 0

col 0; len 1; (1):  64

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 01

从结果里我们可以看到,即便我这里用的是rebuildoracle这里也已经将上述global rowid的错误修正。

 

为什么会这样?

很简单,因为在indexunusable的情况下,即使是直接rebuildoracle这里也会走全表扫描。

SQL> select status from dba_indexes where index_name='IDX_TESTINDEX_PVALUE';

 

STATUS

--------

VALID

 

SQL> explain plan for alter index idx_testindex_pvalue rebuild;

 

Explained

 

SQL> select * from table(dbms_xplan.display);

 

PLAN_TABLE_OUTPUT

--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

| Id  | Operation              |  Name                 | Rows  | Bytes | Cost  |

--------------------------------------------------------------------------------

|   0 | ALTER INDEX STATEMENT  |                       |  9802 | 19604 |    13 |

|   1 |  INDEX BUILD NON UNIQUE| IDX_TESTINDEX_PVALUE  |       |       |       |

|   2 |   SORT CREATE INDEX    |                       |  9802 | 19604 |       |

|   3 |    INDEX FAST FULL SCAN| IDX_TESTINDEX_PVALUE  |  9802 | 19604 |       |

--------------------------------------------------------------------------------

Note: cpu costing is off, PLAN_TABLE' is old version

 

11 rows selected

 

SQL> alter index idx_testindex_pvalue unusable;

 

Index altered

 

SQL> select status from dba_indexes where index_name='IDX_TESTINDEX_PVALUE';

 

STATUS

--------

UNUSABLE

 

SQL> explain plan for alter index idx_testindex_pvalue rebuild;

 

Explained

 

SQL> select * from table(dbms_xplan.display);

 

PLAN_TABLE_OUTPUT

--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

| Id  | Operation              |  Name                 | Rows  | Bytes | Cost  |

--------------------------------------------------------------------------------

|   0 | ALTER INDEX STATEMENT  |                       |  9802 | 19604 |    13 |

|   1 |  INDEX BUILD NON UNIQUE| IDX_TESTINDEX_PVALUE  |       |       |       |

|   2 |   SORT CREATE INDEX    |                       |  9802 | 19604 |       |

|   3 |    PARTITION RANGE ALL |                       |       |       |       |

|   4 |     TABLE ACCESS FULL  | TESTINDEX             |  9802 | 19604 |    13 |

--------------------------------------------------------------------------------

Note: cpu costing is off, PLAN_TABLE' is old version

 

12 rows selected

 

16:35 DataReport的数据共享改进 (3547 Bytes) » AnySQL.net

    用oramon将数据库的主要负载信息收集到了性能数据库, 用DataReport去显示这些性能数据时, 发现要写很多个SQL语句, 要不同的列显示一次, 例如要显示三幅图片(平均Load值, 用户CPU消耗, SQL执行次数)就得执行三个SQL.

WEBCHART.QUERY_1=SELECT TIME, LOAD FROM DATABASE_LOAD ...
WEBCHART.QUERY_2=SELECT TIME, CPUUSR FROM DATABASE_LOAD ...
WEBCHART.QUERY_3=SELECT TIME, EXECS FROM DATABASE_LOAD ...

    其实DATABASE_LOAD是一个宽表, 可以一次查询出多个列的数据来, 几个图片可以共享一次查询的结果, 就可以减少数据库的执行次数, 提高页面访问速度. 如下所示, 只需要指定某个查询的SQL语句为减号.

WEBCHART.XCOL=TIME
WEBCHART.QUERY_1=SELECT TIME, LOAD, CPUUSR, EXECS
  FROM DATABASE LOAD ...
WEBCHART.YCOL_1=LOAD
WEBCHART.QUERY_2=-
WEBCHART.YCOL_2=CPUUSR
WEBCHART.QUERY_3=-
WEBCHART.YCOL_3=EXECS

    最近做了一次大的数据库改造, 用DataReport分析性能数据比较繁烦, 因此才注意到这个方面的性能提升.

Relative Posts:

07:41 LOB segment上的HW enqueue问题 (9205 version) (6963 Bytes) » eagle's home

第一次遇到这个问题是在2006年,后来陆陆续续的遇到过好几次,都是在9205的版本上。

可是一直没有在自己的blog上好好总结一下。我以为自己写过了,今天想找给别人时才发现没有写过。

数据库版本当时为9205。问题表现为大量的active session等待在mod为6的HW enqueue上。

当前获得enqueue的session执行非常慢,平时小于一秒钟的DML操作现在大约需要几十秒钟才能完成。

查询v$lock得到下面的信息:

SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
———- — ———- ———- ———- ———- ———- ———-
3575 HW 16 159461642 6 0 18 1
3546 HW 16 159461642 0 6 257 0
3542 HW 16 159461642 0 6 348 0
3468 HW 16 159461642 0 6 31 0
3329 HW 16 159461642 0 6 46 0
2634 HW 16 159461642 0 6 171 0
2565 HW 16 159461642 0 6 94 0
2532 HW 16 159461642 0 6 77 0
2497 HW 16 159461642 0 6 304 0
2179 HW 16 159461642 0 6 386 0
1972 HW 16 159461642 0 6 116 0
1927 HW 16 159461642 0 6 183 0
1777 HW 16 159461642 0 6 209 0
1690 HW 16 159461642 0 6 249 0
1637 HW 16 159461642 0 6 164 0
1616 HW 16 159461642 0 6 17 0
1601 HW 16 159461642 0 6 109 0
1353 HW 16 159461642 0 6 134 0
1236 HW 16 159461642 0 6 320 0
1218 HW 16 159461642 0 6 64 0
1163 HW 16 159461642 0 6 234 0
1150 HW 16 159461642 0 6 291 0
1082 HW 16 159461642 0 6 150 0
1074 HW 16 159461642 0 6 219 0
987 HW 16 159461642 0 6 195 0
713 HW 16 159461642 0 6 374 0
683 HW 16 159461642 0 6 331 0
672 HW 16 159461642 0 6 275 0
535 HW 16 159461642 0 6 361 0
404 HW 16 159461642 0 6 400 0

ID2是DBA,我们可以用“oracle DBA convertor”工具得到相应的File#和Block#

SQL> !dba 159461642

Oracle DBA convertor

by Stephan Haisley, Center Of Expertise, Oracle Corporation
RDBA: 0×981310a (159461642) File#: 38 Block#: 78090

SQL> select segment_name,partition_name,header_file,header_block from
SQL> dba_segments where segment_name=’SYS_LOB0000009458C00013$$’;

SEGMENT_NAME PARTITION_NAME HEADER_FILE HEADER_BLOCK

—————————————- —————————— ———– ————
SYS_LOB0000009458C00013$$ SYS_LOB_P19 38 65289
SYS_LOB0000009458C00013$$ SYS_LOB_P20 46 52489
SYS_LOB0000009458C00013$$ SYS_LOB_P21 38 78089 — 78090 = 78089+1

然后你会发现这个Block并不是Lob segment header,而是Lob segment header后面一个block。注意这一点非常重要,这是这一类问题的标准特征。

如果等待的block是segment header,那么你遇到的不是本文所描述的问题。

一般的HW enqueue发生在segment header上,而后面这个block是什么呢?

说到这个block,要从Lob segment的undo方式说起。Lob segment将old image存放在自己的segment中,而不是undo segment中。
这块存放old image的空间的大小有两种方式来定义,pctversion或者是retention。
对此不熟悉的同学可以参考我以前的两篇文章当ORA-01555遇到了LOBPCTVERSION or RETENTION?

而这个block就是用来记录这些可以被回收的old image blocks,采用bitmap方式存储。

当可回收的old image space超过PCTVERSION定义的百分比时,新增加的数据可以从这些old image space中回收。

但是oracle在回收时有两个bug:

Bug 4867884(Note:4867884.8) - Lob HW lock contention with space reclaimation — fixed in 10.1.0.6, 10.2.0.3, 11g (Future version)
Bug 4113930(Note:4113930.8) - Space reclaimation shows HW enqueue contention with concurrent insert of LOBs — fixed in 9.2.0.8 , 10.1.0.5 , 10.2.0.1

触发这个bug有两个条件
1. 可回收的old image space超过PCTVERSION定义的百分比
2. concurrent transaction超过一定的数值,具体的值不清楚,我遇到问题时的concurrent transaction数目大约为30

所以解决这个问题就从上面两点来入手。

1.

最快解决问题的方法就是调大pctversion。

dump segment header后的那个block(38,78090)
alter system dump datafile 38 block 78090;

找到一行free blocks:10109615,根据这个可以算出free blocks所占的百分比,然后调整pctversion使其大于该百分比,这样就不会有回收空间的动作。
这一方法可以很快的解决问题,就是比较浪费空间。如果有维护的时间,可以通过move的方式来回收空间。

2.

从segment上的并发数入手,例如减少并发量,或者hash partition table使每个segment上面的并发数减少

06:46 恩墨科技为中电财提供顾问咨询及容灾服务 (3817 Bytes) » Oracle Life

©作者:eygle 发布在 eygle.com

近日恩墨科技中国电力财务有限公司提供数据库容灾环境实施及顾问咨询工作。

近年来,国内越来越多的公司开始认识到数据安全的重要,以各种手段和方式开始实施数据库安全架构。在众多的可选方案中,Oracle的DataGuard技术以其成本低、可用性及安全性能够满足绝大多数需求成为了很多企业的首选。在下个月即将发布的Oracle Database 11gR2版本中,Oracle Active DataGuard技术将得到进一步增强,可以预计,这一新版的的卓越新特性将为Oracle带来更多的客户

中国电力财务有限公司(以下简称中国电财)成立于1993年,是经中国银行业监督管理委员会批准的一家全国性非银行金融机构。中国电财注册资本金50亿元,由国家电网公司控股、各省(市、区)电力公司等50家电力企、事业单位共同参股组建。经银监会批准,中国电财拥有东北、西北、华中和华东等多家区域性分公司,注册资本金、资产规模、利润总额等多项指标在国内财务公司行业中均名列前茅,在电力和金融行业树立了良好的企业形象,当选为中国财务公司协会理事长单位。

客户的数据库采用Oracle Database 10g RAC架构,异地容灾以Oracle DataGuard技术为主体实现。

感谢用户及合作伙伴用友公司的信赖与支持,希望稳健架构的实施可以帮助用户实现数据安全和业务连续性的需要。


相关文章|Related Articles

评论数量(1)|Add Comments

本文网址:

2009-06-28 Sun

20:30 当无统计信息的时候ix_sel的值取决于什么 (53845 Bytes) » Focus on Oracle

在"利用10053分析执行计划的一个例子"这篇文章里,我提到----"这个默认值不是固定的,感觉这里这个默认值取决于Blks"。

 

当时为什么这么说是因为我看到的所有关于10053的文章中都或直接或隐约的指出当没有统计信息的时候,oracle是根据Blks来计算默认的统计信息。

 

呵呵,这个观点误导了我,我们来看一下真相是什么。

 

SQL> create table tb0624 (type number,ts timestamp) pctfree 90;

 

Table created

 

SQL> begin

  2  for i in 1..10000 loop

  3  insert into tb0624 values (1,sysdate);

  4  insert into tb0624 values (3,sysdate);

  5  end loop;

  6  commit;

  7  end;

  8  /

 

PL/SQL procedure successfully completed

 

SQL> begin

  2  for i in 1..10 loop

  3  insert into tb0624 values (2,sysdate);

  4  end loop;

  5  commit;

  6  end;

  7  /

 

PL/SQL procedure successfully completed

 

SQL> exec dbms_stats.gather_table_stats('IPRA','TB0624',CASCADE=>FALSE,METHOD_OPT => 'FOR ALL INDEXED COLUMNS')

 

PL/SQL procedure successfully completed

 

SQL> SELECT NUM_ROWS,BLOCKS,AVG_ROW_LEN FROM USER_TABLES WHERE TABLE_NAME='TB0624';

 

  NUM_ROWS     BLOCKS AVG_ROW_LEN

---------- ---------- -----------

     20010        438          14

 

SQL> create index idx_type on tb0624(type);

 

Index created

 

这里我们分别修改NUM_ROWSBLOCKSAVG_ROW_LEN,以便来看看ix_sel到底取决于哪个值。

 

1、修改#Blks后的10053

SQL> exec dbms_stats.set_table_stats(ownname => 'IPRA',tabname => 'TB0624',numblks => 538);

 

PL/SQL procedure successfully completed

 

SQL> SELECT NUM_ROWS,BLOCKS,AVG_ROW_LEN FROM USER_TABLES WHERE TABLE_NAME='TB0624';

 

  NUM_ROWS     BLOCKS AVG_ROW_LEN

---------- ---------- -----------

     20010        538          14

 

***************************************

BASE STATISTICAL INFORMATION

***********************

Table Stats::

  Table: TB0624  Alias: TB0624

    #Rows: 20010  #Blks:  538  AvgRowLen:  14.00

Index Stats::

  Index: IDX_TYPE  Col#: 1

    LVLS: 1  #LB: 40  #DK: 3  LB/K: 13.00  DB/K: 267.00  CLUF: 801.00

***************************************

SINGLE TABLE ACCESS PATH

  Column (#1): TYPE(NUMBER)  NO STATISTICS (using defaults)

    AvgLen: 22.00 NDV: 625 Nulls: 0 Density: 0.0015992

  Table: TB0624  Alias: TB0624    

    Card: Original: 20010  Rounded: 200  Computed: 200.10  Non Adjusted: 200.10

  Access Path: TableScan

    Cost:  121.28  Resp: 121.28  Degree: 0

      Cost_io: 119.00  Cost_cpu: 7837335

      Resp_io: 119.00  Resp_cpu: 7837335

  Access Path: index (AllEqGuess)

    Index: IDX_TYPE

    resc_io: 17.00  resc_cpu: 151884

    ix_sel: 0.004  ix_sel_with_filters: 0.004

    Cost: 17.04  Resp: 17.04  Degree: 1

  Best:: AccessPath: IndexRange  Index: IDX_TYPE

         Cost: 17.04  Degree: 1  Resp: 17.04  Card: 200.10  Bytes: 0

可以看到,当我在只改变#Blks的情况下,ix_sel的值未变。

 

2、修改#Rows后的10053

SQL> exec dbms_stats.set_table_stats(ownname => 'IPRA',tabname => 'TB0624',numblks => 438,numrows => 30010);

 

PL/SQL procedure successfully completed

 

SQL> SELECT NUM_ROWS,BLOCKS,AVG_ROW_LEN FROM USER_TABLES WHERE TABLE_NAME='TB0624';

 

  NUM_ROWS     BLOCKS AVG_ROW_LEN

---------- ---------- -----------

     30010        438          14

 

***************************************

BASE STATISTICAL INFORMATION

***********************

Table Stats::

  Table: TB0624  Alias: TB0624

    #Rows: 30010  #Blks:  438  AvgRowLen:  14.00

Index Stats::

  Index: IDX_TYPE  Col#: 1

    LVLS: 1  #LB: 40  #DK: 3  LB/K: 13.00  DB/K: 267.00  CLUF: 801.00

***************************************

SINGLE TABLE ACCESS PATH

  Column (#1): TYPE(NUMBER)  NO STATISTICS (using defaults)

    AvgLen: 22.00 NDV: 938 Nulls: 0 Density: 0.0010663

  Table: TB0624  Alias: TB0624    

    Card: Original: 30010  Rounded: 300  Computed: 300.10  Non Adjusted: 300.10

  Access Path: TableScan

    Cost:  100.66  Resp: 100.66  Degree: 0

      Cost_io: 98.00  Cost_cpu: 9127191

      Resp_io: 98.00  Resp_cpu: 9127191

  Access Path: index (AllEqGuess)

    Index: IDX_TYPE

    resc_io: 18.00  resc_cpu: 173806

    ix_sel: 0.005999  ix_sel_with_filters: 0.005999

    Cost: 18.05  Resp: 18.05  Degree: 1

  Best:: AccessPath: IndexRange  Index: IDX_TYPE

         Cost: 18.05  Degree: 1  Resp: 18.05  Card: 300.10  Bytes: 0

可以看到,当我在只改变#ROWS的情况下,ix_sel的值已经发生了改变。

 

3、修改AvgRowLen后的10053

SQL> exec dbms_stats.set_table_stats(ownname => 'IPRA',tabname => 'TB0624',numblks => 438,numrows => 20010,avgrlen => 24);

 

PL/SQL procedure successfully completed

 

SQL> SELECT NUM_ROWS,BLOCKS,AVG_ROW_LEN FROM USER_TABLES WHERE TABLE_NAME='TB0624';

 

  NUM_ROWS     BLOCKS AVG_ROW_LEN

---------- ---------- -----------

     20010        438          24

 

***************************************

BASE STATISTICAL INFORMATION

***********************

Table Stats::

  Table: TB0624  Alias: TB0624

    #Rows: 20010  #Blks:  438  AvgRowLen:  24.00

Index Stats::

  Index: IDX_TYPE  Col#: 1

    LVLS: 1  #LB: 40  #DK: 3  LB/K: 13.00  DB/K: 267.00  CLUF: 801.00

***************************************

SINGLE TABLE ACCESS PATH

  Column (#1): TYPE(NUMBER)  NO STATISTICS (using defaults)

    AvgLen: 22.00 NDV: 625 Nulls: 0 Density: 0.0015992

  Table: TB0624  Alias: TB0624    

    Card: Original: 20010  Rounded: 200  Computed: 200.10  Non Adjusted: 200.10

  Access Path: TableScan

    Cost:  100.08  Resp: 100.08  Degree: 0

      Cost_io: 98.00  Cost_cpu: 7125191

      Resp_io: 98.00  Resp_cpu: 7125191

  Access Path: index (AllEqGuess)

    Index: IDX_TYPE

    resc_io: 17.00  resc_cpu: 151884

    ix_sel: 0.004  ix_sel_with_filters: 0.004

    Cost: 17.04  Resp: 17.04  Degree: 1

  Best:: AccessPath: IndexRange  Index: IDX_TYPE

         Cost: 17.04  Degree: 1  Resp: 17.04  Card: 200.10  Bytes: 0

可以看到,当我在只改变AvgRowLen的情况下,ix_sel的值未变。

 

从上述测试中我们可以很清晰的得出如下结论:

在无统计信息的情况下,ix_sel的值取决于#Rows,而不是取决于#Blks
08:59 GreenPlum 架构 [Flickr] (454 Bytes) » DBA notes

Fenng(dbanotes) posted a photo:

GreenPlum 架构

GreenPlum 还是给DB集群带来一些新的思路和可能的。

或许,DBA 真的不应该只关注关系数据库了。

02:00 Twitter 一周 for 2009-06-28 (4669 Bytes) » Sky.Jian 朝阳的天空

  • MySQL5.0.3开始,VARCHAR的最大存储限制已经更改为字节数,且不再存在单独的固定限制,而受到单条记录除TEXT和BLOB类型字段外最大长度不超过65536 Bytes的限制。定义的M仍是字符数,所以定义后的VARCHAR字段实际最大可存放数据长度与字符集相关的。 #
  • RT: @fireshort: mysql的varchar是从哪个版本开始储存最多65535个字符的?一直记得是只能存储最多255个字符的啊。[5.0.3] #
  • 今年到目前起床最早的一个周末,7:30 醒! #
  • RT: @chagel: rt @virushuo上海塌房事件直播 http://is.gd/1fi3z [这幢房子倒得还真是很整齐啊,幸好还没有人入住,否则...] #
  • RT:@kimihuang: 为了纪念MJ,今晚晚上去跑西湖了,从北山路开始,苏堤一个往返…在上白堤…在edushi.com上测量了一下,刚好10公里 (via @karlzheng)关键是用多少时间。10公里不多,我晨跑也有5公里呢[锻炼身体的长跑在于慢而久,而不是快] #
  • RT: @eygle: 据说 Oracle Database 11gr2下个月亚洲将举行新闻发布会 #
  • RT: @esunchien: 迈克尔·杰克逊的唱片和传记要大卖了。 #
  • RT: @esunchien: … RT @momoran80: RT: @huairen: RT @virushuo: 强烈谴责百度 http://is.gd/1cKCd 【未成年人请勿点击,成人教育图片,当然出品人:更懂中文的那口子】[很强大] #
  • RT:@Fenng:方滨兴,首先提出了建设国家网络与信息安全基础设施的理念,并组织研制、实现了相应的系统…在信息安全理论方面,将涉及了物理、运行(网络安全)、数据(狭义的信息安全)及内容的信息安全概念给出了统一的形式化定义…[是要人肉么?] #
  • RT: @Fenng: 寻找 Zion http://www.dbanotes.net/review/zion.html [这个值得一推] #
  • RT: @niedongming: 刚才求证了下,原来我们公司自己架了DNS服务器,直接把google访问地址解析到了访问IP上去了。[造福大家啊,值得称颂] #
  • RT: @smallfish_xy: RT: @sky000: 太阳… Linux下通过Pidgin上msn也能中毒?【这个要顶,没遇见过】[好几个人反应总收到我MSN发出的减肥广告信息。。。] in reply to smallfish_xy #
  • 太阳… Linux下通过Pidgin上msn也能中毒? #

Powered by Twitter Tools.


作者: Sky.Jian  发布在:www.jianzhaoyang.com  欢迎 订阅本站Feed
Copyright © 2004-2008, 可以任意转载, 但转载时务必以超链接形式标明文章原始出处 和 作者信息 及 版权声明
链接:http://www.jianzhaoyang.com/sky-on-twitter/twitter-%e4%b8%80%e5%91%a8-for-2009-06-28 )

No related posts.

00:08 Use index_desc (3714 Bytes) » 玉面飞龙的BLOG

常见的例子,表中记录按照creation_date作purge,且该字段上有个索引。

如果不加index_desc hint,purge job执行时间长了可能会越来越慢。如下consistent read明显要比current read多很多。是因为Index range scan从index tree的最左面开始扫描,扫描了很多空块。

SQL> DELETE FROM  vltb_data_0   where creation_date < (SYSDATE - 3)  and rownum < 1000;
999 rows deleted.

———————————————————-
| Id  | Operation          | Name                        |
———————————————————-
|   0 | DELETE STATEMENT   |                             |
|   1 |  DELETE            | RULE_OBJECT_ATTR_DATA_0     |
|*  2 |   COUNT STOPKEY    |                             |
|*  3 |    INDEX RANGE SCAN| RULE_OBJECT_ATTR_DATA_0_IX3 |
———————————————————-
Predicate Information (identified by operation id):
—————————————————
2 - filter(ROWNUM<1000)
3 - access(”CREATION_DATE”<SYSDATE@!-3)

Statistics
———————————————————-
1  recursive calls
21167  db block gets
427848  consistent gets

0  physical reads
1341824  redo size
1  sorts (memory)
0  sorts (disk)
999  rows processed

通过添加index_desc, Index range descending scan从index tree的中间或者右边进入扫描,更快定位到存在纪录的block.

SQL> DELETE /*+ index_desc(rule_object_attr_data_0) */ FROM  vltb_data_0   where creation_date < (SYSDATE - 3)  and rownum < 1000;
999 rows deleted.

Statistics
———————————————————-
1  recursive calls
21177  db block gets
59  consistent gets
288  physical reads
1368592  redo size
814  bytes sent via SQL*Net to client
833  bytes received via SQL*Net from client
3  SQL*Net roundtrips to/from client
1  sorts (memory)
0  sorts (disk)
999  rows processed

从而避免了无用功。这样的例子时常在工作中遇到。

—————-人工分割线————————

最近上海一个刚盖的差不多快结盘的13层房子倒了一个,整体倒的。是有一个小的房地产开发公司开发的。全国人民都知道了。

估计会对房地产市场特别是中小房地产开发公司开发的楼盘带来严重信任危机。那些早些年盖的二手房或许将火爆。

很壮观。



2009-06-27 Sat

22:36 discuz on amoeba 乱码问题解决 (486 Bytes) » Amoeba 开发者博客

Amoeba 默认设置支持客户端设置编码的方式是 : set names gbk 其他方式目前还没考虑到。

Discuz遇到编码问题,可以通过修改 include/db_mysql.class.php 里的 设置编码方式改成:

 set names utf8

 –即支持utf8编码格式

  原文来自:

http://hi.baidu.com/hlxwell/blog/item/ea0d445913af102d2834f0d5.html

08:50 Amoeba for Mysql 1.0.0-BETA 版本发布 (791 Bytes) » Amoeba 开发者博客

该版本基于0.32版本之上进行bugs fixed,非常感谢阿权提供的一些bug列表

这次版本跳跃比较大,也是我打算在amoeba这个项目花下时间的决心。因此将amoeba提升到新的起点1.0.0版本

下面是这次主要的变更:

1、修复sql解析 explain 关键字开始的sql
2、修复FORCE INDEX (xx) 之类的sql无法解析问题
3、修复包含转义符合在内的sql 比如:insert into xx values(’\'test\’)
4、修复包含 Order by rand()的sql
5、调整默认 网络接受发送缓冲区成128k

下载地址: http://www.sf.net/projects/amoeba

05:17 Twitter每日推荐一位推友计划 (第二季) (13862 Bytes) » DBA notes

作者:Fenng 发布在 dbanotes.net. BLOG 墙外订阅数量,点击则可进行订阅

我在Twitter上的这个试验性的:每日推荐一位推友计划,已经来到了第二季。在 5月35 日那几天短暂被封之后,Twitter 用户依旧活跃。短短的消息即可迅速传递我们的情绪,表达我们的愤怒。这是这个时代最好的工具。

再次说一下推荐的几条理由:

  • Twitter 背后的那个人在某个领域要有一定影响力或者有趣或是 Twitter 内容比较有价值
  • 订阅人数(followers)不超过 500 个才可能会加入推荐候选列表。如果订阅者少于100,基本发现很难形成良性互动,有的新用户就会意兴阑珊--毕竟自言自语不是很有意思的事情。而一旦超过200,就基本到了一个比较良性的循环了。对于超过500的,基本上不用推荐也会自然增长,边界效益不高。
  • 非商业行为。同时避免侵犯隐私,每个人的介绍以网络可以搜索到的为准。
  • 在每个工作日进行推荐,一般在下午 15:00 左右,这个时间也是公司下午茶时间,基本不影响工作。

如果要跟踪这个推荐计划,请 follow 我(@Fenng ),另请参考之前的第一季。介绍语基本上都是我拟就的,如果有不合适之处,那肯定是我没说好。如果你看到某个 Twitter 用户比较有趣,可以给我留言( @Fenng) 告诉我。




  • @mujiang
    朱一, 曾是Abebook.com架构师,现 Amazon的 Database Architect,海外华人,不明白为啥总自称木匠:) 另:他友情帮我们做了TOP第四章初稿。
  • @fengchunpei
    冯春培, 常年活动于ITPUB,id: biti_rainy,发帖数万... Oracle ACE,现任阿里巴巴 B2B 研究员。在国内数据库界人称大师。
  • @yeka52
    周筠, 博文视点出版社(武汉)负责人,IT图书出版界奇才,众多重量级IT技术图书出自她的策划。 对所有教育及出版,以及设计相关的事情都感兴趣。
  • @hdcola
    黄冬, 为国内 FreeBSD 社区默默贡献不小。曾负责过新浪研发中心的多个部门和产品,后离职创业,现在供职无限讯奇,为中国移动12580核心合作伙伴。
  • @delphij
    Xin LI, FreeBSD commiter...新浪北美的,操作系统界领域的大牛
  • @freebat
    王慧文, 校内网的Cofounder。现为 冒泡网 的站长。maopao.com 是一个类似 Twitter/FriendFeed 的网站,据说要做自己的特色。
  • @eygle
    盖国强, 知名数据库专家, 是数本Oracle技术图书的作者。恩墨科技创建人(八卦一下,恩墨是他儿子的名字) 他的个人站点:http://www.eygle.com/ 。
  • @lastmailbox
    邹欣, 微软亚洲研究院资深人士。搜索一下,你就知道! 《移山之道》、《编程之美》(合作) 作者。 他的Blog耐看。
  • @funy
    付宁, SNS第三方应用开发者与实践者,他捣鼓的 SNS 应用曾日收入$2000。Web2.0 创业人。
  • @wulujia
    吴鲁加, 资深网络安全技术牛人。大成天下创建者,总经理。他的Blog:http://wulujia.com/
  • @milkr
    稻草, 设计师,Blogger,虾米网设计总监。 UCDChina 杭州联系人,他的Blog:http://www.v4uu.com/blog/
  • @chedong
    车东, 著名Blogger, 资深互联网人,前雅虎高级技术经理,前BlogBus CTO,现已加盟搜狐,任职产品总监。
  • @yanhui
    阎辉, CSDN 产品总监(对CSDN有意见可以找他)。《程序员》杂志创刊就做,五年,后任CSDN执行总编。现在在做高端技术管理者社区CTO俱乐部,以及正在研究和实践基于社区的新型商务产品模型。
  • @chndonny
    陈栋,来自阿里 B2B DBA 团队,技术杠杠嘀, 爱好摄影。想当年兄弟我刚到杭州的时候就借住在他的房子。
  • @Crossday
    戴志康, Discuz! 创建人。80 后科技精英代表人物之一(其它几个不知道都跑哪里去了)。
  • @hutuworm
    冯亮, 阿里最有趣的技术Geek之一。沉浸于 Linux 系统管理十余年,以此为业逾五载。现为运维架构师。业余偶猎文史哲社政法诸学。《Linux Network Cookbook 中文版》译者。
  • @gaochunhui
    高春辉, 老网民应该都知道他,当年中国个人站长第一人。手机之家(imobile.com.cn)创建人,ECSHOP创建人... 我眼中的老高:仍然对技术有着极高热情的家伙。
  • @Kimihuang
    黄航飞, 老阿里人,我们并肩为支付宝战斗过。电子产品爱好者,F1粉丝。现在在阿里妈妈(淘宝)做产品运营。擅长给支付宝找茬。他的Blog是我见过用Mac用户装修最差的一个,他的女儿比他可爱,哈
  • @syutlyc
    杨帆, cnBeta.com 副站长(有IT新闻给他爆料吧)。IT Pro, 企业解决方案咨询顾问,曾在微软总部IT部门和微软中国的顾问咨询部门工作了4年。擅长微软企业服务器产品。喜好古典音乐。
  • @zhuzhijun
    祝志军,互联网资深人士。TechWeb.com.cn 创建人。老祝的Blog 最近很有料:http://zhijun.techweb.com.cn/
  • @zhangjb
    张翼轸,潮人。我喜欢看他的Blog: http://blog.earlzhang.com/ "用理性的视角去探讨护肤品、时尚、男装、奢侈品、爱情这些风花雪月" 。
  • @xdanger
    戴云杰,VeryCD 的联合创建人、CTO(有谁没有用过电驴麽?) 。技术高手,Geek。也是 Google 和苹果的粉丝。
  • @arthur369
    西乔,Magicome公司创建人,提供 Web 技术开发项目外包开发及产品端顾问咨询。这位同学在2009年六月四日结婚,新郎是 @virushuo 同学 。
  • @aimingoo
    周爱民, 刚加盟支付宝的牛人。国内软件开发界资深软件工程师。《Delphi源代码分析》、《大道至简》、《JAVASCRIPT语言精髓与编程实践》等图书作者。
  • @Peoplecbc
    人物·志,中文网志年会人际交流平台-http://people.cnbloggercon.org/
  • @jinghuaz
    晶华, 前谷歌中国,现在在美国 Mozilla Labs。关于用户体验与开源软件。
  • @csdncto
    蒋涛, CSDN 掌门人。《程序员》杂志总编。IT人,太极拳、围棋重度爱好者。
  • @horse
    詹膑, 高校教师, 独立顾问, Blogger, 奇遇花园咖啡馆老板。典型的跨界人。
  • @jeffz_cn
    赵劼, 网名老赵,洋名Jeffrey Zhao。目前担任上海柏盛网络技术有限公司架构师。InfoQ 中文站编辑。
  • @zhidong
    王志东, 软件英雄。中文之星、四通利方和新浪创始人。点击科技创始人,Lava-Lava ,正在体验 Twitter 中。
  • @gigix
    熊节, 笔名透明,知名 IT 技术专家,现为 Thought Works 咨询师。多本重量级图书的译者,最近的译作是《卓有成效的程序员》。
  • @zhuangbiaowei
    庄表伟, 年轻的老技术人。印客网(http://www.inker.com.cn/) 技术总监。
  • @anson_ho
    何烨, Geek. 独立策划人. 涉猎:网络、电台、公关、品牌、汽车。他的Blog:http://www.anson-ho.com
  • @ShooterPlayer
    沈晟, 射手网(http://shooter.cn/)站长,射手播放器(http://splayer.org/)主要开发者。
  • @jinhuang
    黄劲, 走秀网创始人之一。走秀网(http://www.zoshow.com/) 是一家定位于时尚电子商务领域的新锐网站。
  • @liuyan
    今日推荐推友:刘岩, 六间房(6.cn)的创建人。刘岩参与过新浪网和亚信公司的融资和上市,并领导完成了亚信公司对杭州德康公司的收购。现任六间房CEO。



现在是广告时间:

  • @BetaCafe
    贝塔咖啡馆...支持Twitter订咖啡,定期发放Twitter 优惠券
  • @JobsDigg
    帮找工作 ...我的实验性项目
  • @Alipay
    来自支付宝的半官方小道消息

最后,或许你应该关注一下这个" 热门锐推用户"榜

--EOF--


相关文章|Related Articles

评论数(7)|添加评论 | 最近作者还说了什么? Follow Fenng@Twitter
本文网址:

DBA Notes 理念: 用简约的技术取得最大的收益...

04:22 DBA日记 第二部 (31) 外来的和尚好念经 4月30日 IO优化 (27157 Bytes) » DBA&#26085;&#35760;

1.1.1. 4月30日 IO优化

今天早上没什么事,明天就开始7天的五一长假了,所以我今天和公司的同事打了个招呼,今天就不过去了。这个五一节并没有什么安排,只是准备6号的时候出去跑一趟短途,要么去桔钓沙游泳,要么去巽寮湾玩玩。早上躺在床上看了会电视,才懒懒的爬起来洗脸刷牙,吃完早饭的时候已经块10点钟了。打开电脑收了下邮件,发现马工发了一封邮件给我:

老白,您好!

自月中系统好转之后,明喻真又开始冗长的不着边际的动作了。

老万和明喻关于数据库方面增加费用的谈判也没有成功,按他的说法是明喻他们负责项目的这个部门准备放弃项目了,但是销售和客户部门却坚持要把项目继续下去,而继续项目的方法不是找你商量而是通过内部挖国内外资源的办法来进行,对于你的数据库方面的计划他们也没有任何回应,把我郁闷得......

18号那天我离开青岛开始休假,直到26日回青岛,这期间关于项目的事情我一概不过问,听之任之。

现在明喻他们的动作:

1、请了一个系统测试工程师准备进行实验室测试,以“科学”的数据得出一个系统和硬件的解决方案;

2、请了新西兰的数据库专家Richard来进行数据库方面的分析和优化,以得出一个数据库方面的优化解决方案。

目前第一个动作正在准备过程中,用的是LoadRunner软件,这两天东软在学习如何用LoadRunner准备测试脚本,非常不顺利,居然来教他们用LoadRunner的工程师对于如何根据东软现在的应用架构配置LoadRunner这一步都没能跨过去,两天了,没有什么进展。

第二个动作限于英语水平我没能跟老外有更多的交流,他有几个举措:增加EVA3000的4块硬盘、增加VA7410的3块硬盘以提高IO吞吐,昨天改了一个操作系统参数,虽然没有对数据库参数进行修改,但昨晚停数据库进行系统数据和应用数据DD复制,而后在数据库重起时东软居然发现参数文件找不到了,于是用了一个旧版本的,而且后来是在奕华的协助下把数据库给起来了,害我又没有睡好觉。今天中午老蒋说找到了原来的参数文件,要重启数据库。

老万的时间要求是必须在5月31日解决问题,但是明喻做法可真是有趣啊!

我读了邮件,马上给马工打了个电话,他对目前的情况比较悲观,在老万的压力下,Richard已经准备不经过严格的测试直接开始做优化动作了。他的第一个动作就是优化IO,明喻他们已经申请好了几块硬盘,今天晚上就要实施存储的扩容,按照Richard的想法,增加磁盘的数量,让IO分布到更多的磁盘上,可以提高IO的性能。另外Richard建议取消每个REDO LOG组的镜像,改为每个组一个member,以减少IO的负担。Richard 的做法是IO性能优化中常用的办法,我也经常使用这个方法,但是在老万他们这个系统里,目前不仅仅是IO存在问题,和IO相比,更为危险的是CPU资源。一旦IO性能得到提升,每秒钟将有更多的事务被处理,那样就要消耗更多的CPU资源,一旦CPU出现了瓶颈,闩锁争用将急剧上升,数据库的整体性能不会提高反而会有所下降。

刚刚和马工通完电话,老万的电话就打了进来,他告诉我今天晚上Richard想对IO进行优化,增加几块硬盘。Richard提出的取消一个日志组成员的建议被东软拒绝了,东软他们不愿意降低系统的可靠性来换取IO成本的下降。老万问我Richard的方案我是否赞成。

我说:“万科,如果纯粹是优化IORichard的做法无可厚非。不过按照目前系统的情况,单独优化IO风险很大,一旦CPU过载那么后果更严重。最好是能够首先减少一些逻辑读,再进行IO优化,两个步骤一起实施才能确保万无一失。”

老万实际上也有类似的担心,于是老万希望我能够给Richard发个邮件,把这个问题和Richard说一下,看看Richard能不能考虑的充分一些再做动作。于是我马上写了封邮件给Richard。写完邮件后,我发了个短信给明喻,让明喻通知Richard收一下邮件。通过第一次和Richard的口语交流,我对自己的口语能力基本上丧失了信心。

发完邮件后一看时间已经快中午了,由于早饭吃的晚,也没有心思做午饭吃了。冰箱里还有半个西瓜,就权当我的午饭了吧。吃完西瓜回到电脑边上的时候,发现Richard已经回了邮件:

Hi Jackson,

Just following up on this message, 

I agree that if we improve IO we will run into the CPU bottleneck. The CPU is very high now. 

My reason for fixing the IO first is if we upgrade the server to faster/more CPU then we will 

not get any more performance from the server as the additional resource will be waiting IO.

So I believe that we need to change both but to change them one at a time. IO is the bottleneck now, 

then only when this is removed will we raise the processing to become a CPU bottleneck. The question 

is if we can improve the IO performance will the system performance meet the customer needs without 

the cost of the server upgrade.

As to Memory the Oracle database has over 6Gb of memory now for SGA. If this is not enough then how 

large does the memory on this system need to be?. It is already 2Gb memory per CPU so is on the larger 

size. What would your suggestion for the system memory size?

As to the code, I agree it is not only hard but expensive. I am interested in your comments re the 

tuning that you plan to do. Mingyu do you know why this has been put on hold?.

Best regards

Richard

这封信是发给我,同时抄送明喻的,很明显最后一句"Mingyu do you know why this has been put on hold?"是问明喻的。在这封邮件里Richard认为CPUIO都需要调整,但是必须一个一个做,他准备首先从IO调整入手。Richard认为IO调整单独做没有问题,这是基于封闭系统的理论,如果平均每秒事务的数量是固定的,那么像Richard所说的一样,CPU负载不会大幅度提升。另外一种可以这么调整的情况是CPU资源比较充足。但是目前的情况恰恰都不是这两种情况,CPU已经出现了较为严重的瓶颈,但是Richard并没有意识到这一点。我在给Richard的邮件中谈到了排队效用,排队效应这个词汇是我自己创造的,可能Richard并没有明白是什么意思,我把排队效应翻译成“effect of waiting queue”,当时觉得翻译的还有点靠谱,现在看来这不是一个很准确的翻译,起码Richard并没有看懂。

今天晚上Richard要在EVA 3000上增加四块盘,组成一个RAID 0+1,在VA7400上增加3块盘,组成一个RAID 5Richard准备把REDO LOG移到EVA3000上新创建的这个RAID 0+1大的磁盘组上,同时从EVA 3000上迁移部分写IO较多的数据文件到这个盘组上。然后会将VA7400上一部分写入较少的数据文件移到VA7400上的新增的磁盘组上,以减轻存储的负担,提高IO的性能。Richard这个动作做的很漂亮,肯定能较大幅度的提高IO的性能,不过这也正是我所担心的,Richard这一手的效果越好我越担心,我担心这哥们会把我前一阵子花了九牛二虎之力才降下来的CPU负载再折腾上去。

下午的时候,马工又给我打了一个电话,他经过一番努力,希望劝阻今天晚上的盘阵扩容操作,不过最终还是失败了。明天是5.1节,这个系统的业务量肯定会比今天有所上升,而今晚这个操作让马工十分担心,如果明天系统真的出了什么问题,那么这个5.1节都过不好了。我正和马工聊着,突然马工说:“老白,你别挂电话,万科有话和你说”。

老万第一句就问我:“老白,明天你准备去哪里玩?”

我说:“明天能上哪玩去,5.1节哪都是人,出去玩?还不如在家睡大觉。”刚说完,我就觉得好像哪里不对。还没等我补充,老万就接上话了:“那好,老白,明天你帮我盯一下系统,今天晚上这个操作我是实在不放心,你在家就好了,我也就放心了。为了今天晚上的这个扩容,我明天也只能在办公室里了,我们明天一起聊QQ”。原来老万这个老狐狸在这里等着我呢,既然前面已经说了明天在家睡觉,我也就不好推辞了,只能答应了老万,明天在家上网,陪他聊QQ

 

03:06 常见索引扫描方式(四):INDEX SKIP SCAN (59953 Bytes) » DBARoad:我的DBA之路

索引跳跃式扫描(INDEX SKIP SCAN),需要在CBO模式下才能起作用,当查询谓词中不带有前导列,且前导列唯一值较少时,才有可能用上该索引扫描方式。下面来看看INDEX SKIP SCAN 是如何扫描的:

准备测试数据:

SQL> create table test(x number,y number);
 
Table created.
 
SQL> insert into test
  2  select decode(mod(rownum,2),0,1,2),rownum
  3  from dba_objects where rownum&lt;10000;
 
9999 rows created.
 
SQL> commit;
 
Commit complete.
 
SQL> create index ind_xy on test(x,y);
 
Index created.
 
SQL> exec dbms_stats.gather_table_stats('SYS','TEST');
 
PL/SQL procedure successfully completed.
 
SQL> set autot trace exp
SQL> select * from test where y=5;
 
Execution Plan
----------------------------------------------------------
Plan hash value: 854635220
 
---------------------------------------------------------------------------
| Id  | Operation        | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT |        |     1 |     6 |     3   (0)| 00:00:01 |
|*  1 |  INDEX SKIP SCAN | IND_XY |     1 |     6 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - access("Y"=5)
       filter("Y"=5)
 
SQL> select * from test where y between 1000 and 1200;
 
Execution Plan
----------------------------------------------------------
Plan hash value: 217508114
 
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |   202 |  1212 |     5   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| TEST |   202 |  1212 |     5   (0)| 00:00:01 |
--------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter("Y"< =1200 AND "Y">=1000)
 
SQL> set autot off

为了让类似于“y between 1000 and 1200”的范围查询也走索引,我们修改一下统计信息:

SQL> exec dbms_stats.set_table_stats('SYS','TEST',numrows=>1000000,numblks=>3000000);
 
PL/SQL procedure successfully completed.
 
SQL> exec dbms_stats.set_index_stats('SYS','IND_XY',NUMROWS=>1000000,NUMLBLKS=>3000000);
 
PL/SQL procedure successfully completed.
 
SQL> set autot trace exp
SQL> select * from test where y between 1000 and 2500;
 
Execution Plan
----------------------------------------------------------
Plan hash value: 854635220
 
---------------------------------------------------------------------------
| Id  | Operation        | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT |        |   150K|   880K|   407K  (1)| 10:27:02 |
|*  1 |  INDEX SKIP SCAN | IND_XY |   150K|   880K|   407K  (1)| 10:27:02 |
---------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - access("Y">=1000 AND "Y"< =2500)
       filter("Y"<=2500 AND "Y">=1000)

先设置10046事件,看看读取的是哪些BLOCK:

SQL> alter system flush buffer_cache;
 
System altered.
 
SQL> oradebug setmypid
Statement processed.
SQL> oradebug event 10046 trace name context forever,level 12;
Statement processed.
SQL> select * from test where y=1000;
 
         X          Y
---------- ----------
         1       1000
 
PARSING IN CURSOR #3 len=31 dep=0 uid=0 oct=3 lid=0 tim=28576548594261 hv=3600506749 ad='3c10ae90'
select * from test where y=1000
END OF STMT
PARSE #3:c=10000,e=9280,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,tim=28576548594242
BINDS #3:
EXEC #3:c=0,e=152,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=28576548594524
WAIT #3: nam='SQL*Net message to client' ela= 4 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=28576548594595
WAIT #3: nam='db file sequential read' ela= 74 file#=1 block#=69522 blocks=1 obj#=109868 tim=28576548594838
WAIT #3: nam='db file sequential read' ela= 106 file#=1 block#=69523 blocks=1 obj#=109868 tim=28576548595032
WAIT #3: nam='db file sequential read' ela= 18 file#=1 block#=69524 blocks=1 obj#=109868 tim=28576548595141
FETCH #3:c=0,e=533,p=3,cr=3,cu=0,mis=0,r=1,dep=0,og=1,tim=28576548595199
WAIT #3: nam='SQL*Net message from client' ela= 515 driver id=1650815232 #bytes=1 p3=0 obj#=109868 tim=28576548595798
WAIT #3: nam='db file sequential read' ela= 19 file#=1 block#=69535 blocks=1 obj#=109868 tim=28576548595905
WAIT #3: nam='db file sequential read' ela= 50 file#=1 block#=69536 blocks=1 obj#=109868 tim=28576548596016
WAIT #3: nam='db file sequential read' ela= 18 file#=1 block#=69548 blocks=1 obj#=109868 tim=28576548596098
FETCH #3:c=0,e=294,p=3,cr=5,cu=0,mis=0,r=0,dep=0,og=1,tim=28576548596129
WAIT #3: nam='SQL*Net message to client' ela= 1 driver id=1650815232 #bytes=1 p3=0 obj#=109868 tim=28576548596199
WAIT #3: nam='SQL*Net message from client' ela= 500 driver id=1650815232 #bytes=1 p3=0 obj#=109868 tim=28576548596726
STAT #3 id=1 cnt=1 pid=0 pos=1 obj=109868 op='INDEX SKIP SCAN IND_XY (cr=8 pr=6 pw=0 time=517 us)'

可以看到Block读取的顺序为:69522->69523->69524->69535->69536->69548

再来看看“y between 1000 and 2500”的BLOCK读取顺序:

select * from test where y between 1000 and 2500
WAIT #3: nam='db file sequential read' ela= 966 file#=1 block#=69522 blocks=1 obj#=109868 tim=28579403261397
WAIT #3: nam='db file sequential read' ela= 101 file#=1 block#=69523 blocks=1 obj#=109868 tim=28579403261570
WAIT #3: nam='db file sequential read' ela= 17 file#=1 block#=69524 blocks=1 obj#=109868 tim=28579403261677
WAIT #3: nam='db file sequential read' ela= 19 file#=1 block#=69525 blocks=1 obj#=109868 tim=28579403274372
WAIT #3: nam='db file sequential read' ela= 19 file#=1 block#=69526 blocks=1 obj#=109868 tim=28579403291497
WAIT #3: nam='db file sequential read' ela= 19 file#=1 block#=69535 blocks=1 obj#=109868 tim=28579403294076
WAIT #3: nam='db file sequential read' ela= 51 file#=1 block#=69536 blocks=1 obj#=109868 tim=28579403294187
WAIT #3: nam='db file sequential read' ela= 18 file#=1 block#=69537 blocks=1 obj#=109868 tim=28579403297464
WAIT #3: nam='db file sequential read' ela= 19 file#=1 block#=69538 blocks=1 obj#=109868 tim=28579403313975
WAIT #3: nam='db file sequential read' ela= 20 file#=1 block#=69548 blocks=1 obj#=109868 tim=28579403325960

为69522->69523->69524->69525->69526->69535->69536->69537->69538->69548

我们先将几个重要的BLOCK DUMP出来,再来分析下INDEX SKIP SCAN为何是这样读取的。
查询首先读取的分支节点69522:

Branch block dump
=================
header address 9223372041152863300=0x80000001002f9c44
kdxcolev 1
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 3
kdxcosdc 0
kdxconro 25
kdxcofbo 78=0x4e
kdxcofeo 7741=0x1e3d
kdxcoavs 7663
kdxbrlmc 4263827=0x410f93
kdxbrsno 0
kdxbrbksz 8040 
kdxbr2urrc 0
row#0[8028] dba: 4263828=0x410f94 ##BLOCK:69524
col 0; len 2; (2):  c1 02
col 1; len 3; (3):  c2 09 05      对应Y值804
col 2; TERM
row#1[8017] dba: 4263829=0x410f95 ##BLOCK:69525
col 0; len 2; (2):  c1 02
col 1; len 2; (2):  c2 11         对应Y值1600
col 2; TERM
row#2[8005] dba: 4263830=0x410f96 ##BLOCK:69526
col 0; len 2; (2):  c1 02
col 1; len 3; (3):  c2 18 61      对应Y值2396
col 2; TERM
row#3[7993] dba: 4263831=0x410f97 ##BLOCK:69527
col 0; len 2; (2):  c1 02
col 1; len 3; (3):  c2 20 5d      对应Y值3192
col 2; TERM
row#4[7981] dba: 4263832=0x410f98
col 0; len 2; (2):  c1 02
col 1; len 3; (3):  c2 28 59
col 2; TERM
row#5[7969] dba: 4263833=0x410f99
col 0; len 2; (2):  c1 02
col 1; len 3; (3):  c2 30 55
col 2; TERM
row#6[7957] dba: 4263834=0x410f9a
col 0; len 2; (2):  c1 02
col 1; len 3; (3):  c2 38 51
col 2; TERM
row#7[7945] dba: 4263835=0x410f9b
col 0; len 2; (2):  c1 02
col 1; len 3; (3):  c2 40 4d
col 2; TERM
row#8[7933] dba: 4263836=0x410f9c
col 0; len 2; (2):  c1 02
col 1; len 3; (3):  c2 48 49
col 2; TERM
row#9[7921] dba: 4263837=0x410f9d
col 0; len 2; (2):  c1 02
col 1; len 3; (3):  c2 50 45
col 2; TERM
row#10[7909] dba: 4263838=0x410f9e
col 0; len 2; (2):  c1 02
col 1; len 3; (3):  c2 58 41
col 2; TERM
row#11[7897] dba: 4263839=0x410f9f ##BLOCK:69535
col 0; len 2; (2):  c1 02
col 1; len 3; (3):  c2 60 3d      对应Y值9560
col 2; TERM
row#12[7885] dba: 4263840=0x410fa0 ##BLOCK:69536
col 0; len 2; (2):  c1 03
col 1; len 3; (3):  c2 04 40      对应Y值363
col 2; TERM
row#13[7873] dba: 4263841=0x410fa1 ##BLOCK:69537
col 0; len 2; (2):  c1 03
col 1; len 3; (3):  c2 0c 3c      对应Y值1159
col 2; TERM
row#14[7861] dba: 4263842=0x410fa2 ##BLOCK:69538
col 0; len 2; (2):  c1 03
col 1; len 3; (3):  c2 14 38      对应Y值1955
col 2; TERM
row#15[7849] dba: 4263843=0x410fa3 ##BLOCK:69539
col 0; len 2; (2):  c1 03
col 1; len 3; (3):  c2 1c 34       对应Y值2751
col 2; TERM
row#16[7837] dba: 4263844=0x410fa4
col 0; len 2; (2):  c1 03
col 1; len 3; (3):  c2 24 30
col 2; TERM
row#17[7825] dba: 4263845=0x410fa5
col 0; len 2; (2):  c1 03
col 1; len 3; (3):  c2 2c 2c
col 2; TERM
row#18[7813] dba: 4263846=0x410fa6
col 0; len 2; (2):  c1 03
col 1; len 3; (3):  c2 34 28
col 2; TERM
row#19[7801] dba: 4263847=0x410fa7
col 0; len 2; (2):  c1 03
col 1; len 3; (3):  c2 3c 24
col 2; TERM
row#20[7789] dba: 4263848=0x410fa8
col 0; len 2; (2):  c1 03
col 1; len 3; (3):  c2 44 20
col 2; TERM
row#21[7777] dba: 4263849=0x410fa9
col 0; len 2; (2):  c1 03
col 1; len 3; (3):  c2 4c 1c
col 2; TERM
row#22[7765] dba: 4263850=0x410faa
col 0; len 2; (2):  c1 03
col 1; len 3; (3):  c2 54 18
col 2; TERM
row#23[7753] dba: 4263851=0x410fab
col 0; len 2; (2):  c1 03
col 1; len 3; (3):  c2 5c 14
col 2; TERM
row#24[7741] dba: 4263852=0x410fac ##对应BLOCK:69548
col 0; len 2; (2):  c1 03
col 1; len 3; (3):  c2 64 10       对应Y值9915
col 2; TERM
----- end of branch block dump -----

再DUMP出BLOCK:69535,可以看出该BLOCK有X值为1的索引条目,也有X值为2的索引条目,我们可以这样认为,该BLOCK是索引中X值为1的最左边,X值为2的最右边:

Leaf block dump
===============
header address 9223372041152863324=0x80000001002f9c5c
kdxcolev 0
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 3
kdxcosdc 0
kdxconro 401
kdxcofbo 838=0x346
kdxcofeo 1654=0x676
kdxcoavs 816
kdxlespl 0
kdxlende 0
kdxlenxt 4263840=0x410fa0
kdxleprv 4263838=0x410f9e
kdxledsz 0
kdxlebksz 8016
row#0[8000] flag: ------, lock: 0, len=16
col 0; len 2; (2):  c1 02
col 1; len 3; (3):  c2 60 3d
col 2; len 6; (6):  00 41 0f 89 01 cd
row#1[7984] flag: ------, lock: 0, len=16
col 0; len 2; (2):  c1 02
col 1; len 3; (3):  c2 60 3f
col 2; len 6; (6):  00 41 0f 89 01 cf
..........................................
.................省略部份.................
..........................................
row#217[4532] flag: ------, lock: 0, len=16
col 0; len 2; (2):  c1 02
col 1; len 3; (3):  c2 64 5f
col 2; len 6; (6):  00 41 0f 8a 01 21
row#218[4516] flag: ------, lock: 0, len=16
col 0; len 2; (2):  c1 02
col 1; len 3; (3):  c2 64 61
col 2; len 6; (6):  00 41 0f 8a 01 23
row#219[4500] flag: ------, lock: 0, len=16
col 0; len 2; (2):  c1 02                  X:1
col 1; len 3; (3):  c2 64 63               Y:9998(X为1时,Y的最大值)
col 2; len 6; (6):  00 41 0f 8a 01 25
row#220[4485] flag: ------, lock: 0, len=15
col 0; len 2; (2):  c1 03                  X:2
col 1; len 2; (2):  c1 02                  Y:1 (X为2时,Y的最小值)
col 2; len 6; (6):  00 41 0e da 00 00
row#221[4470] flag: ------, lock: 0, len=15
col 0; len 2; (2):  c1 03
col 1; len 2; (2):  c1 04
col 2; len 6; (6):  00 41 0e da 00 02
row#222[4455] flag: ------, lock: 0, len=15
col 0; len 2; (2):  c1 03
col 1; len 2; (2):  c1 06
col 2; len 6; (6):  00 41 0e da 00 04
..........................................
.................省略部份.................
..........................................
row#400[1654] flag: ------, lock: 0, len=16
col 0; len 2; (2):  c1 03
col 1; len 3; (3):  c2 04 3e
col 2; len 6; (6):  00 41 0e da 01 68
----- end of leaf block dump -----
 
SQL> select max(y) from test where x=1;
 
    MAX(Y)
----------
      9998
SQL> select dump(9998,16) from dual;    
 
DUMP(9998,16)
---------------------
Typ=2 Len=3: c2,64,63

从上面这些trace中可以看出,查询读取了Branch block后,便分别在X值为1,及X值为2的两个范围内的leaf block中进行扫描。例如查询,y=1000,读取顺序为:

69522->69523->69524->69535->69536->69548:
 
69522 Branch block
 
69523 X值为1的leaf block的起始BLOCK
69524 Y值范围为8041599,所以1000可能在其中,需要读取
 
69535 X值为1的leaf block的结束BLOCK,及X值为2的leaf block的起始BLOCK
 
69536 Y值范围为3631158,所以1000可能在其中,需要读取
69548 X值为2的leaf block的结束BLOCK

查询,y between 1000 and 2500 读取顺序为:

69522->69523->69524->69525->69526->69535->69536->69537->69538->69548
 
69522 Branch block
 
69523         X值为1的leaf block的起始BLOCK
69524 - 69526 Y值范围为8043191,“y between 1000 and 2500”可能在其中,需要读取
 
69535         X值为1的leaf block的结束BLOCK,及X值为2的leaf block的起始BLOCK
 
69536 - 69538 Y值范围为3632750,“y between 1000 and 2500”可能在其中,需要读取
69548         X值为2的leaf block的结束BLOCK

我们可以这样认为,INDEX SKIP SCAN就相当于要在X=1及X=2的两个子索引(也可以说是虚拟索引)中进行扫索,因而,前导列X如果有多个不同的值,就要在多个不同的子索引中进行扫描,个数越多,代价也越高,优化器最终也就不会选择使用INDEX SKIP SCAN了。例如,我们更改X的唯一值为10000,查询就不再采用INDEX SKIP SCAN:

SQL> exec dbms_stats.SET_COLUMN_STATS('SYS','TEST','X',DISTCNT=>10000);
 
PL/SQL procedure successfully completed.
 
SQL> select * from test where y=1000;
 
Execution Plan
----------------------------------------------------------
Plan hash value: 1066898076
 
-------------------------------------------------------------------------------
| Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |        |   100 |   600 |   389K  (1)| 14:06:10 |
|*  1 |  INDEX FAST FULL SCAN| IND_XY |   100 |   600 |   389K  (1)| 14:06:10 |
-------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter("Y"=1000)

— The End —

2009-06-26 Fri

20:36 如何快速安全的更改表的owner (3969 Bytes) » eagle's home

前两天有人问我这个问题,我说你先自己去搜索下答案吧。

后来他说没有找到合适的方法,我搜索了一下,竟然发现没有人提到exchange partition的方法。

exchange partition的方法是最安全,也是最快速的方法。

所以这里写出这种方法供大家参考。

假设有A,B两个用户,我们想把TEST表从A用户移到B用户。

我们以非分区表作为例子:

SQL> conn a/a
Connected.
SQL> create table test(x int);

Table created.

SQL> create index test_idx on test(x);

Index created.

SQL> insert into test select rownum from dual connect by level <10000;

9999 rows created.

SQL> commit;

Commit complete.

SQL> conn b/b
Connected.

SQL> create table temp(x int) partition by range (x)
2 (partition part0 values less than (-1),
3 partition part1 values less than (maxvalue));

Table created.

SQL> create table test(x int);

Table created.

SQL> create index temp_idx on temp(x) local;

Index created.

SQL> create index test_idx on test(x);

Index created.

SQL> alter table temp exchange partition part1 with table a.test including indexes without validation;

Table altered.

SQL> alter table temp exchange partition part1 with table test including indexes without validation;

Table altered.

SQL> select count(*) from a.test;

COUNT(*)
———-
0

SQL> select count(*) from b.test;

COUNT(*)
———-
9999

如果是分区表,操作过程如下:

SQL> conn a/a
Connected.

SQL> create table test(x int) partition by range (x)
2 (partition part0 values less than (100),
3 partition part1 values less than (maxvalue));

Table created.

SQL> create index test_idx on test(x) local;

Index created.

SQL> insert into test select rownum from dual connect by level <1000;

999 rows created.

SQL> commit;

Commit complete.

SQL> conn b/b
Connected.
SQL> create table temp(x int);

Table created.

SQL> create index temp_idx on temp(x);

Index created.

SQL> create table test(x int) partition by range (x)
2 (partition part0 values less than (100),
3 partition part1 values less than (maxvalue));

Table created.

SQL> create index test_idx on test(x) local;

Index created.

SQL> select count(*) from a.test;

COUNT(*)
———-
999

SQL> select count(*) from b.test;

COUNT(*)
———-
0

SQL> alter table a.test exchange partition part0 with table temp including indexes without validation;

Table altered.

SQL> alter table test exchange partition part0 with table temp including indexes without validation;

Table altered.

SQL> select count(*) from a.test;

COUNT(*)
———-
900

SQL> select count(*) from b.test;

COUNT(*)
———-
99

SQL> alter table a.test exchange partition part1 with table temp including indexes without validation;

Table altered.

SQL> alter table test exchange partition part1 with table temp including indexes without validation;

Table altered.

SQL> select count(*) from a.test;

COUNT(*)
———-
0

SQL> select count(*) from b.test;

COUNT(*)
———-
999

复合分区表的情况大同小异,大家可以自己试验一下。

09:21 rac安装报错和修复小结 (8458 Bytes) » OracleBlog.cn

一、rac安装步骤主要分以下几步:
1、安装操作系统。
2、配置时间同步,如ntp
3、创建oracle用户和配置rsa和dsa
4、配置hosts文件
5、配置hangcheck-timer
6、配置共享存储(ocr和voting disk)
7、安装clusterware(crs)
8、配置asm
9、安装数据库软件和创建实例。

二、cluster如果需要重装,可以
方法1、按照$CRS_HOME/install/rootdeinstall.sh进行卸载。
方法2、手工卸载:

rm /etc/oracle/*
rm -f /etc/init.d/init.cssd
rm -f /etc/init.d/init.crs
rm -f /etc/init.d/init.crsd
rm -f /etc/init.d/init.evmd
rm -f /etc/rc2.d/K96init.crs
rm -f /etc/rc2.d/S96init.crs
rm -f /etc/rc3.d/K96init.crs
rm -f /etc/rc3.d/S96init.crs
rm -f /etc/rc5.d/K96init.crs
rm -f /etc/rc5.d/S96init.crs
rm -Rf /etc/oracle/scls_scr
rm -f /etc/inittab.crs
cp /etc/inittab.orig /etc/inittab
rm -rf /tmp/.oracle 
rm -rf /var/tmp/.oracle
rm -f /etc/oracle
rm -Rf /u01/app/oracle/product/10.2.0/crs_1
rm -f /ocfs/clusterware/ocr
rm -f /ocfs/clusterware/votingdisk

三、检查clusterware是否安装正确:

rac1->/u01/app/oracle/product/10.2.0/crs_1/bin/cluvfy stage -post crsinst -n rac1,rac2

四、检查crs是否运行正常

crsctl check crs

五、rac无法启动,检查发现是asm无法启动,在asm的启动时有报错:

Total System Global Area   92274688 bytes
Fixed Size                  1217884 bytes
Variable Size              65890980 bytes
ASM Cache                  25165824 bytes
ORA-15032: not all alterations performed
ORA-15063: ASM discovered an insufficient number of disks for diskgroup"RECOVERYDEST"
ORA-15063: ASM discovered an insufficient number of disks for diskgroup "DG1"

这个时候检查给asm的raw device的权限,linux下重启时会自动把raw device的属主改为root,因此需要在/etc/rc.local文件中添加(有时修改/etc/udev/permissions.d/50-udev.permissions文件没用,必须修改rc.local文件):
chown oracle:dba /dev/raw/raw[1-3]
chmod 660 /dev/raw/raw[1-3]

六、如果某些application状态为UNKNOWN,可以用crs_stop NAME -f,再crs_start NAME -f来重启解决:

rac2-> crs_stat -t
Name           Type           Target    State     Host       
------------------------------------------------------------
……   
ora....C2.lsnr application    ONLINE    ONLINE    rac2       
ora.rac2.gsd   application    ONLINE    UNKNOWN   rac2       
……     
 
rac2->
rac2-> crs_stat
NAME=ora.devdb.db
TYPE=application
TARGET=ONLINE
STATE=ONLINE on rac1
……
NAME=ora.rac2.gsd
TYPE=application
TARGET=UNKNOWN
STATE=ONLINE on rac2
……
 
rac2-> crs_stop ora.rac2.gsd -f
Attempting to stop `ora.rac2.gsd` on member `rac2`
Stop of `ora.rac2.gsd` on member `rac2` succeeded.
 
rac2-> crs_start ora.rac2.gsd -f
Attempting to start `ora.rac2.gsd` on member `rac2`
Start of `ora.rac2.gsd` on member `rac2` succeeded.
 
rac2-> crs_stat -t
Name           Type           Target    State     Host       
------------------------------------------------------------
…… 
ora....C2.lsnr application    ONLINE    ONLINE    rac2       
ora.rac2.gsd   application    ONLINE    ONLINE    rac2       
……     
rac2->

06:20 ODU的几种恢复场景 » 老熊的三分地-Oracle、UNIX、数据恢复

2009-06-25 Thu

21:03 In Memory of Michael Jackson » Chanel [K]
05:51 如何安全的split partition » eagle's home

2009-06-24 Wed

 123
 123