木匠的微型博客 Charlie Twitter

    follow me on Twitter

    Wednesday, June 17, 2009

    Cowichan River Tube Trip 漂流

    一年一度的温哥华岛自然水域漂流又要开始啦! 欢迎留言报名. 跟我的http://twitter.com/mujiang也行.
    在这里,您可以接受加拿大成人仪式, 品尝杂草(weed), 根据个人喜好选择,不存在任何强迫. 嘻嘻.

    上甘岭河(Cowichan River)是我平生见到的最好玩的漂流, 水质纯天然,清澈,水量充足,安全,偶然有一些激流(一共两处),有惊无险,赶紧靠岸就行了,胆大的可以冒进. 去年鄙人躲了,今年一定要尝试一下激流速降.

    Cowichan River Tube Trip

    The Date

    June 28th 2009

    The Float

    Skutz Falls to Marie Canyon - 2hr ride, not including optional time spent beached

    Equipment needed

    1. Tube - If you don't have one, we can buy them at the local tire shop in Duncan for $20 or Zellers in Tillicum Mall has These for $24 (BESTEST TUBE EVEEER!!!!)
    2. Beverages - What ever you feel like drinking (NO GLASS BOTTLES ALLOWED)
    3. Cooler(s) - Communal, if anybody has a big cooler that would be great
    4. Cooler Tube - Gets blown up around the cooler to keep it a float and safe (also acts as an emergency spare)
    5. River Shoes - I use a old pair of runners, some sort of footware is a must(IMO)
    6. Rope - Or bungy to tie tubes to the trucks
    7. Sunscreen!!
    8. What ever else you might want to bring

    The Time Line

    • 9 AM - Meet at ABE
    • 9:30 AM - Leave for Duncan
    • 10:15 AM - Buy Tires and Snacks if wanted
    • 10:30 AM - Buy Beverages and head off
    • 11:00ish AM - Start Tube ride
    • Enter time warp time can not be quantified

    The Tubers

    1. Doug - Have Car will drive
    2. Megan - Has Car if needed
    3. Charlie - Will go if I can find someone take care of my puppy and my shin wound recovered.

    Wednesday, June 10, 2009

    scrum 群殴扭打

    如果你们也在实施敏捷(Agile)软件开发,你就知道scrum是啥意思了, 就是在一个开发小组里面,每人每天早晨简短汇报工作进度.

    每天早上的Scrum都会讲昨天干了什么,今天要干什么. 周一早上,我就说昨天我去沃尔玛采购了幼犬用品,今天继续开发在线库存系统的Database API.

    大家沉默了三秒钟,突然开始集体爆笑. 原来每天的Scrum大伙都是来报到凑个数,没几个人关心别人干了什么.
    就是做和尚撞钟,混个工分.

    Friday, May 29, 2009

    PL/SQL代码可以有多大size limit

    PL/SQL程序块的最大尺寸是67108864 (2**26) DIANA节点, 主要是受shared memory pool的限制.
    PL/SQL程序块包括(Package)包头,包体,独立存储过程,或者匿名程序块. eBay好像是统统使用匿名PL/SQL块.

    但是对于DIANA节点,我们只能获取一个大概的数字,通过查询视图USER_OBJECT_SIZE,PARSED_SIZE列里面是"扁平化的flattened" DIANA节点数:


    SQL> SELECT * FROM user_object_size WHERE name = 'PKG1';

    NAME TYPE SOURCE_SIZE PARSED_SIZE CODE_SIZE ERROR_SIZE
    ----------------------------------------------------------------
    PKG1 PACKAGE 46 165 119 0
    PKG1 PACKAGE BODY 82 0 139 0


    根据Tom和Tim(http://oracle-base.com/)的理想境界,去除Java/C/.Net等前端应用代码里面的所有SELECT/INSERT/UPDATE/DELETE/MERGE,把那些丑陋的SQL扔到九霄云外.
    --不是说Java Developer不会写SQL, 而是他们的强项不在数据库. 模块化,专业分工,高效合作,

    鄙人最近三个月奋发图强,努力工作,大力推行Database API, 消灭Java应用里面的SQL代码,书写了很多PL/SQL代码,有一个接近100K,编译一遍耗时数秒, 就开始担心最大尺寸问题. 结果PARSED_SIZE只有6115, 离67108864(64M)还差点远着哩.

    当然鄙人也在认真学习Agile编程里面的Refactoring代码重构, 尽量将重复使用的代码段抽象成子过程,或者工具包.

    参考:
    Oracle® Database PL/SQL Language Reference
    11g Release 1 (11.1)

    Appendix C PL/SQL Program Limits
    .

    Sunday, May 24, 2009

    Give and Take - IT Club聚会主题征集

    眼看五月份要交白卷了, 转一篇我在维多利亚IT俱乐部的帖子:

    鄙人有一个想法:

    就是大伙罗列出你关心/感兴趣的主题, 和你能够共享/贡献的主题.
    把答案发给木匠,然后鄙人整理筛选,协助GengLi 和 老Shan协调安排, 使以后的聚会更加有针对性.

    好了, 举个例子, 比如 木匠的共享和兴趣:

    贡献
    ----
    *) 给IT老兵的六点建议
    *) 数据库应用开发的糟糕模式与实践 Performance Anti-Patterns in Database-Driven
    Applications
    *) JDBC/.Net应用的高效数据库存取
    *) GTD 时间管理

    *) 自由泳 训练
    *) 露营 + 密林狂奔
    *) 训练小狗
    *) Cowichan lake 轮胎漂流

    感兴趣
    -- -- ---
    如和构建易于线性扩展的Web应用系统架构 (Scale out)
    Agile项目管理
    Agile软件开发流程

    户外露营 + 密林狂奔
    小狗训练
    川菜烹饪
    划船 及 安全


    - MJ

    Thursday, April 30, 2009

    今日好图 流感传染途径How swine flu gets transmitted….

    猪流感是这样传染的:

    Wednesday, April 29, 2009

    SQL Server技术讲座-维多利亚IT Club

    [IT Club] IT 技术讲座--5月16日,星期六,下午2:30
    Address: 2121 Cedar Hill Cross Rd.

    欢迎IT及各界人士前来捧场,结交新朋友,拓展人脉网络, 一定会帮助到您的职业发展和生活琐事.


    以下是来自 John 黄 的介绍:

    ***

    大家好!5月份的讲座由我来说说。 N多个月前讲SQL Replication,弄了60多页,讲得口干舌燥,我想听的人也很辛苦。 这一次我准备了30多页和一些Demo, 希望不要太枯燥,也不要给大家和我带来什么负担。。。。。。

    这一次的话题是SQL Server 的 Locking and Blocking。听这个名字就不像一个有意思的话题, 但是只要牵扯到SQL Server 编程就无法逃避。内容还会涉及到由于Locking and Blocking 所引申出的其他话题,如数据库的设计,编程,性能调整,管理, 和SQL Server 2008 新特性等等,但是不会很多,主要还是集中精力论述Locking and Blocking。我真心邀请Orcle或者其他数据库专家们到场能给我们对应的功能实现。这样能让我们的讲座更加丰富一些。最后如果有时间,我给大家演示SQL Serer Application Locks的应用。

    时间:5月16日,星期六,下午2:30
    地点: UVIC大学旁边那个教堂(谁知道具体地址请补充)

    下面的连接是给大家做参考。与讲座关系不大,但是在讲座中有可能会提及但是不会详尽描述。

    Troubleshooting Performance Problems in SQL Server 2005

    [url]http://www.microsoft.com/technet/prodtechnol/sql/2005/tsprfprb.mspx[/url]

    PSS SQL Server Engine Blog

    [url]http://blogs.msdn.com/psssql/default.aspx[/url]

    Performance Stats Script

    [url]http://blogs.msdn.com/psssql/archive/2007/02/21/sql-server-2005-performance-statistics-script.aspx[/url]

    MSDN Webcast: SQL Server 2008 Advanced Troubleshooting with Extended Events

    [url]http://msevents.microsoft.com/cui/WebCastEventDetails.aspx?culture=en-US&EventID=1032356291&CountryCode=US[/url]

    Bob Beauchemin's Blog: Series in August 2007

    [url]http://www.sqlskills.com/blogs/bobb/default,month,2007-08.aspx[/url]


    KB 271509: INF: How to Monitor SQL Server 2000 Blocking


    黄志勇
    John H
    Microsoft Certified Master -- SQL Server 2008

    Friday, April 24, 2009

    Twitter guide使用指南

    自从上个月注册了一个Twitter用户以后,把个Twitter用的不亦乐乎,基本没有功夫更新博客了.
    木匠的鸟鸣: http://twitter.com/mujiang

    这里就引用一篇Twitter使用指南,给鄙人的博客凑个数.

    TrackBack: http://www.yeeyan.com/articles/view/16551/36190

    利用它来与你的同行取得联系

    除了Twitter外网上有一大堆社区和社交网络型站点,但Twitter仍是我的最爱之一!事实上在Twitter上follow我的人数比我那个设计博客的订阅用户数还要多。

    假设你是一位设计师,我确信总有一些网站和博客是你会定期访问的,我也确信你喜欢通过查看他人的作品和个人履历站点来获得灵感。只需找到 Twitter上的徽章或按钮并follow这些人。很可能发生的情况是他们也会follow你。然后就只是加入或开启一段对话的问题了。

    在Twitter上有许多设计师和网络工作者(当然也有很多自由撰稿人和博客发布者)。前段时间来自Vandelay Design的Steven写了“Twitter上值得follow的50名设计师”这篇文章,而NETTUTS的Jeffrey将“你应该follow 的9位网页设计师”汇编到了这一清单中。我想这些信息对你开始使用Twitter都将有所帮助。

    花些时间去帮助他人

    最近Go Media的工作人员开始通过Twitter来给他人提供设计帮助。我认为这是一个绝妙的点子!这是多么好的一种回馈社会和帮助他人的方法啊!

    还有很多其他设计师也在做相同的事情 - 比方说,当我看见某人在CSS,PHP甚至发布博客方面存在疑问时,我会尝试着给出最佳答案!当我有疑问时我知道有些人也会尽量帮助我。如果我们都能互相学习那将是一种双赢的局面。

    添加链接到你的个人简历式站点或博客

    Twitter当然不是一个像Behance或Carbonmade那种能上传以前作品的网站,但你可以添加链接到你的个人站点并发布关于你目前的设计项目的信息并邀请别人对你的设计作品做出评价。

    你可以在侧栏上或你发布的信息中添加你个人站点的链接。当然不是每个人都会点开你的个人站点,但那些点开的人将更有可能会联系你并有可能雇佣你因为他们已经在Twitter“听说过”你了。

    谈论一些和你所在行业相关的话题

    你是否读到了一篇和自由职业、设计、写作或博客相关的好文章?为什么不谈论它并让你的朋友知道你喜欢这篇文章呢?IE6下PNG的兼容问题有了新的解决方法?嘿,我想知道相关的信息!

    如果我在某个时候需要将部分工作外包,我也许会联系Twitter上的那个人,因为他以前帮助过我,他很友善,我也把他视为专家,因为看起来他对自己所在的行业很了解。

    回复他人的信息

    我喜欢收到潜在客户发来的邮件,说他们在Twitter上发现了我并且需要为某个项目寻找一名网页设计师。我认为这真的很棒,因为实际上我并没有在Twitter花太多时间,我只不过是时不时地在上面发布些信息。

    有些人会很直接地给你发信息来询问你是否有时间替他工作。你要确保阅读并回复这些信息!我知道,你已经需要查看电子邮件,也许你并不想在Twitter回复更多的人了,但如果回复这些信息能给你带来一份很酷的设计任务或很棒的薪酬呢?这种好事情已经多次在我身上发生了!

    你也来分享下经验吧

    你是如何利用Twitter来寻找客户的?你是把Twitter视为一个非常酷的营销和客户网络拓展工具还是说纯粹只是把它作为一个消磨时间的站点呢?曾有潜在客户通过Twitter联系过你么?你接到那个项目了么?请利用留言系统和大家分享下你的使用技巧以及在Twitter上发生的成功的案例。:)

    推荐
    ---
    http://www.yeeyan.com/groups/show/twitter 译言twitter小组

    Monday, April 13, 2009

    电影推荐 The god must be crazy

    复活节长周末,看完了电影[The god must be crazy]的一集和二集. 觉得该强烈推荐给各位.
    虽然是九十年代初拍摄的,故事以情节取胜,紧凑,幽默,而且富有教育意义.
    如果您觉得没有[疯狂的石头]好看,鄙人按当地的平均小时工资偿还您,大概三个小时. 瞧瞧,到底是研究数据库的,这么精确的数字和逻辑.

    故事是这样的,在非洲大陆内部依然依然生活着一群原始部落族群 bushman,他们有着极强的自然适应能力,轻松的适应了非洲的干旱季节,而不是现代化人类的破坏能力,让自然适应人.
    电影讲述了一群现代人闯入bushman人的生活,以及后面引发的一系列有趣的故事.

    也暗示的讽刺了人对不能理解事物的盲目崇拜,如第一集里面的一个玻璃可乐瓶子.

    一群现代人的复杂矛盾,却被原始人用极其简单的方法给解决了.

    鄙人无法道出所有精髓,您自己慢慢欣赏吧.

    Friday, April 10, 2009

    swim in wild lake 畅游天然湖泊

    过了下个长周末,五月份的维多利亚日,就正式宣告进入夏季,也是维多利亚的天堂季节和旅游旺季,世界各地人民呼呼涌来.

    为了帮助新来的喜欢游泳的华人少走弯路,鄙人在这里介绍一下维多利亚和温哥华的适合游泳的天然湖泊.
    淡水湖泊里面游泳肯定比游泳池里面舒服,也比海水温暖,不用穿保暖泳衣.

    维多利亚:

    1) Durrance lake

    View Larger Map

    2) Matheson lake

    View Larger Map

    维多利亚的名气大,但是不适合游泳的湖泊:

    1) Elk lake and Beaver lake
    2) Thetis lake

    因为人多,把冷水都给搅上来了,而且脏.

    温哥华

    1) Buntzen lake

    View Larger Map

    2) 可能是Rice lake, 过两天找温哥华的同学确认一下.

    View Larger Map



    Enjoy the swimming in natural wild lake !

    Thursday, April 09, 2009

    Easter day复活节

    在加拿大生活,基本上每个月有一个公众假日.

    明天是美好星期五(Good Friday),下周一是复活节(Easter Day),两个公众假日连在了一起, 还没想好咋玩呢.

    我在加拿大度过的第一个复活节是在2006年四月,四月是加拿大西海岸的雨季,当时下着连阴雨,组织了本地一帮朋友开车4小时去了Tofino,一个著名的冲浪胜地,并且以广阔的海滩著称,最大的一个海滩长11公里. Tofino是加拿大国家公园 Pacific rim的一部分, 我们都不会冲浪,就穿越森林,溜海滩,观巨浪.
    "West Coast lifestyle Victoria" 此句经常出现在各种地处维多利亚的公司的招聘广告上,用来吸引外地人士, 听着是很惬意.

    我是大菠萝迷(Diablo II), 听说3.0 在三月发行了,明天去FutureShop看看有没有到货.

    今天在牙医诊所修理了最后两颗牙冠, 如果您刚从中国国内过来,这里牙医服务会让你倍感震撼 (服务质量过于上乘),下文详解. 牙医给我讲了复活节的缩减版故事: 耶稣出生了,走了,又来了,故事完了.

    祝各位节日快乐,赶紧出门享受好天气, 今年四月份没有下雨,多难得.
    ...

    长滩.
    ...

    长滩北段.
    .

    林中木板路(board walk)
    .

    太平洋西海岸原始森林.
    .

    Monday, April 06, 2009

    Soccer fans needed温哥华岛IT公司足球联赛


    温哥华岛高科技公司的足球联赛在沉寂两年后又开始啦. 各位维多利亚的足球爱好者,赶紧出来,享受阳光,驰骋绿茵场.


    Your very own AbeBooks soccer players have 2 upcoming matches against our friends at Genologics…

    AbeBooks VS. GenoLogics

    Come out and enjoy the weather and support your co-workers for these 2 fun games.

    Game 1

    When: Wednesday, April 8th 2009

    Time: 11:45am kickoff

    Where: Vancouver Island Tech Park turf – Layritz
    behind Camosun College Interurban Campus, accessible from Interurban Rd and West Saanich Rd


    Game 2

    When: Wednesday, April 15th 2009

    Time: 12:15pm kickoff

    Where: Finlayson turfTopaz Park, Blanshard St + Finlayson St.



    周三中午占用上班时间踢球是我们公司的传统,差不多10年了.
    .

    Sunday, April 05, 2009

    Talk to COO 合理化建议和沟通

    2009年初,我们公司开始了重新设计和开发库存管理系统,可以用革命(Revolution)来形容,有点背离了Agile提倡的进化(Evolution)主旋律.

    基调比较简单:

    1) 改变Slow-by-slow(row-by-row)慢之又慢的数据处理模式, 启用(bulk loading)打包成批处理.
    2) 合理denormalization,减少不必要的表连接.
    3) BASE第一步: Function split功能拆分 和 Asynchronous process 异步处理.
    异步处理,必然引出数据复制和消息系统, 我们的消息系统数据量一大,就会僵死. 我选择了数据库staging table(数据驿站)来缓存修改的数据,对于staging堆栈表,根据简单处理过的时间键,做列表分区,做到冗余数据的最高效利用 (我一向认为队列消息属于被复制的冗余数据).
    关于设计时间相关的历史数据模型,数据建模宝典(Data Modeling Essentials - Third Edition)推荐了两种方法,一种是Audit Trail(记录数据偏移,从起点累积),一种是Snapshot(历史镜像),我在不同场景都有采用,以后找机会做细节示范.

    有一个业务逻辑的改革遇到了较大的阻力,最后决定直接找COO商议,结果还是很理想的,清除了数据处理设计的最后一道障碍.
    跟产品经理和项目经理谈了很多次,结果是"多一事不如少一事,事不关己,高高挂起",这伙人才懒得从公司盈利的高度考虑问题,所以要转向那些能做决定,能从大局着眼的人士.

    下面简单介绍一下这个高投入低回报的业务功能:

    就是维护书商的产品分类,上传图书数据的时候,捎带检查图书分类表. 每行图书数据里面,包含了图书分类,一个或者多个,如果是新的分类,就在书商图书分类表里增加一行.
    如果删除了某个图书分类包含的所有书籍,就在书商图书分类表里删除掉这个图书分类.

    经常是上传几百万本图书信息,却对书商图书分类未动毫毛,白白浪费掉系统处理能量 来做无谓的检查.

    为啥雅虎没落了,谷歌兴旺了.因为Yahoo在做分类目录,Google再做搜索.
    这个年代,很少有人再通过分类目录一层一层的下钻去找到感兴趣的内容了,一个关键字查询,结果根据相关性排序,一下找到结果.


    有兴趣的产品经理,数据处理设计师和开发人员, 可以看看这个功能的链接:
    http://www.abebooks.com/servlet/BooksBrowse?vendorclientid=65646&page=CLIENT

    Tuesday, March 31, 2009

    另一种方法显示ROWID扩充信息-table function

    TrackBack: http://www.ningoo.net/html/2009/how_to_get_extent_id_from_rowid.html

    NinGoo的把常用工具打包进工具箱的方法很好.
    然而木匠天生缺乏分类和组织能力,一路坚持学习,持续遗忘,自身却没有留下啥积累;好比猴子搬苞谷,抱在怀里的玉米棒永远也不会增多,郁闷.
    所以鄙人决定依靠GTD方法,每周总结学到的新知识,然后放进自己的便携工具箱.

    好了,鉴于本人不喜欢dbms_output.put_line,索性把NinGoo的RowID工具改造成了Table Function.
    通过简单的查询,可以在任何地方使用.

    后面附的PL/SQL Package源代码,包含了许多PL/SQL编程优秀实践,将来找机会慢慢展开来讲.

    用法:

    SQL> select * from table(UTILITY.tb_obj.rowid_info('AAARUtAAEAAABm2AAA'));

    COLUMN_VALUE
    --------------------------------------------------------------------------------
    rowid: AAARUtAAEAAABm2AAA
    file_id: 4
    block_id: 6582
    data_object_id: 70957
    owner: INVDB
    object_name: BOOK_UPLOAD_LOG
    extent_id: 0

    7 rows selected.

    tb_ 是toolbox的缩写.



    工具用户需要的对象权限:

    grant select on dba_objects to utility;
    grant select on dba_extents to utility;

    源代码:

    注意: 如果你还没有安装捕获错误工具包u$err和(instrument)代码跟踪包debug, 可以先用备注屏蔽掉相关的代码.


    CREATE OR REPLACE PACKAGE UTILITY.tb_obj
    /*
    | Copyright Information Here
    |
    | File name:
    |
    | Overview:
    |
    | Author(s):
    |
    | Modification History:
    | Date Who What
    |
    */
    IS

    TYPE print_tab IS TABLE OF varchar2(200);

    FUNCTION rowid_info (p_rowid in varchar2) return print_tab PIPELINED DETERMINISTIC;
    PROCEDURE subprogram_name;

    END tb_obj;
    /

    CREATE OR REPLACE PACKAGE BODY UTILITY.tb_obj
    /*
    | Copyright Information Here
    |
    | File name:
    |
    | Overview:
    Tool box to get object information.

    | Author(s):
    |
    | Modification History:
    | Date Who What
    31-Mar-2009 Charlie (Yi): Create the package.

    It meets user requirements
    It is maintainable
    It runs fast enough to minimize user frustration

    **) Pl/SQL development workflow, Four steps of preparing an application

    - Validate program requirements
    # ask lots of questions
    # what users ask for is not always the easiest way to solve a problem
    # consider other approaches, include business processes and programming algorithms
    - Implement header of the program
    # good name for the program, accurately represent the purpose of the program
    # inputs and outputs
    # overload sub-procedure ?
    - Define the test cases
    # Verify it works
    # how will I know when I am done with this program
    - Build test code

    |
    |
    */
    IS
    PROCEDURE initialize_pkg
    IS
    BEGIN
    DBMS_APPLICATION_INFO.SET_MODULE( 'tb_obj','init' );
    END initialize_pkg;

    FUNCTION rowid_info (p_rowid in varchar2)
    return print_tab PIPELINED DETERMINISTIC
    /*
    | Copyright Information Here
    |
    | File name:
    |
    | Overview: Display extended rowid information.
    |
    | Author(s): Charlie MuJiang
    |
    | Modification History:
    | Date Who What
    31-Mar-2009 Charlie (Yi): Create the function.

    Privilege:

    grant select on dba_objects to utility;
    grant select on dba_extents to utility;

    Call example:

    SQL> select * from table(UTILITY.tb_obj.rowid_info('AAARUtAAEAAABm2AAA'));

    COLUMN_VALUE
    --------------------------------------------------------------------------------
    rowid: AAARUtAAEAAABm2AAA
    file_id: 4
    block_id: 6582
    data_object_id: 70957
    owner: INVDB
    object_name: BOOK_UPLOAD_LOG
    extent_id: 0

    7 rows selected.

    |
    */
    IS

    ln_block_id number;
    ln_file_id number;
    ln_object_id number;
    ln_extent_id number;
    ls_object_name varchar2(30);
    ls_owner varchar2(30);

    PROCEDURE initialize
    IS
    BEGIN
    DBMS_APPLICATION_INFO.SET_ACTION( 'rowid_info' );
    END initialize;

    PROCEDURE cleanup
    IS
    BEGIN
    DBMS_APPLICATION_INFO.SET_MODULE(Null,Null);
    END cleanup;
    BEGIN
    initialize;
    /*
    Main body of program
    */
    debug.f('start by user %s', user);

    select dbms_rowid.ROWID_BLOCK_NUMBER(p_rowid),
    dbms_rowid.ROWID_RELATIVE_FNO(p_rowid),
    dbms_rowid.ROWID_OBJECT(p_rowid)
    into ln_block_id,ln_file_id,ln_object_id
    from dual;

    select owner,object_name
    into ls_owner,ls_object_name
    from dba_objects
    where data_object_id=ln_object_id;

    PIPE ROW(' rowid: '||p_rowid);
    PIPE ROW(' file_id: '||ln_file_id);
    PIPE ROW(' block_id: '||ln_block_id);
    PIPE ROW('data_object_id: '||ln_object_id);

    for c in (
    select extent_id,
    owner, segment_name,partition_name, segment_type,tablespace_name
    from dba_extents
    where
    owner=ls_owner and
    segment_name=ls_object_name and
    file_id=ln_file_id and
    ln_block_id between block_id and block_id + blocks - 1
    )
    loop
    PIPE ROW(' owner: '||c.owner);
    PIPE ROW(' object_name: '||c.segment_name);
    PIPE ROW('partition_name: '||c.partition_name);
    PIPE ROW(' segment_type: '||c.segment_type);
    PIPE ROW(' tbs_name: '||c.tablespace_name);
    PIPE ROW(' extent_id: '||c.extent_id);
    end loop;

    debug.f('process %s rows', SQL%RowCount);

    cleanup;
    EXCEPTION
    WHEN NO_DATA_NEEDED THEN
    cleanup;
    return;
    WHEN OTHERS
    THEN
    /* Don't forget to clean up here, too! */
    cleanup;

    /* Standard error logging mechanism */
    u$err.err;
    RollBack;
    raise;
    END rowid_info;

    PROCEDURE subprogram_name
    /*
    | Copyright Information Here
    |
    | File name:
    |
    | Overview:
    |
    | Author(s):
    |
    | Modification History:
    | Date Who What
    |
    */
    IS
    PROCEDURE initialize
    IS
    BEGIN
    DBMS_APPLICATION_INFO.SET_ACTION( 'subprogram_name' );
    END initialize;

    PROCEDURE cleanup
    IS
    BEGIN
    DBMS_APPLICATION_INFO.SET_MODULE(Null,Null);
    END cleanup;
    BEGIN
    initialize;
    /*
    Main body of program
    */
    debug.f('update %s rows', SQL%RowCount);

    cleanup;
    EXCEPTION
    WHEN OTHERS
    THEN
    /* Don't forget to clean up here, too! */
    cleanup;

    /* Standard error logging mechanism */
    u$err.err;
    --RollBack;
    raise;
    END subprogram_name;

    BEGIN
    initialize_pkg;
    END tb_obj;
    /


    deprecated ROWID hint 废弃的行标识提示

    在Oracle 10g以后,RowID 这个SQL提示就被废弃了.搜索Google也找不到替代方案.
    在一些应用场景里面利用RowID存取路径,还是很有帮助的. 比如回改, 就是在用户界面显示用户感兴趣的数据,数据被修改以后,再更新回数据库.

    那么怎样强制优化器使用存取路径TABLE ACCESS BY ROWID呢? 我暂时发现了两种方法:

    1) 使用No_Index SQL提示
    2) 使用表达式或者运算符禁止索引扫描.

    关于具体的搭建测试环境和演示, 参考文章NO_INDEX hint and deprecated ROWID hint.

    测试结果
    --
    当查询优化器采用TABLE ACCESS BY USER ROWID存取路径时,我们发现逻辑读(Buffer列)由2降到1.

    Saturday, March 28, 2009

    Earth Hour 关灯一小时

    在维多利亚,地球日被提前到了今天,星期六.

    各种人物提出了多种方式度过 "地球一小时".
    比如看电视,点蜡烛.这不还是继续浪费能源吗? 穿了个马甲而已.

    我有两个计划,8:30pm游泳完以后,直接上床睡觉. 或者在黑暗中静思冥想,想想家庭生活有哪些项目可以改进,修马桶,给外墙刷油漆,屋顶换瓦, 想想工作中的哪些数据处理逻辑可以改进,提高系统的扩展性,可靠性,应用各种11g的新特性.

    去野外看星星 也不错,可惜维多利亚阴天下雨; 维多利亚(BC省西海岸)有个体育活动,夜晚健行(night hiking),可以去中国海滩(China beach) 欢德福卡野径(trail),我的同事老奔驰等人去过好几次了,下次跟上他们;
    或者给多年没有联系的老朋友打电话.


    Enjoy sitting in the dark!

    Thank you for your support!

    参考:
    --
    <http://www.earthhour.org/home/> Saturday March 28th @ 8:30pm!

    What is it?
    Switch off your lights for one hour and send a message to the world.

    Reality check:
    Earth Hour is a symbolic event. Turning off our lights for an hour won’t stop climate change but it does demonstrate that our individual action is important and adds up to make a big difference.

    Results & photos from 2008
    What’s happening in Vancouver
    Here are some simple tips to make Earth Hour a success:
    1. Turn off all non-essential lights on Saturday, March 28 at 8:30 pm.
    2. Encourage family, friends and local businesses to participate.
    3. Sign-up (AbeBooks.com already has!)
    10% Off @ WWF Store
    As a thank you for signing up:
    Enjoy 10%* off at the WWF Store where you will find unique and sustainable products. Visit wwfstore.ca and enter promo code EH2009.
    So let’s get some more businesses to sign up & turn off those lights on Saturday night!


    维多利亚大学(UVic)的图书馆.

    Monday, March 09, 2009

    Troubleshooting Oracle Performance下载文件更新

    TrackBack: http://antognini.ch/2009/03/troubleshooting-oracle-performance-downloadable-files/

    像我一样的TOP书迷们注意了, TOP脚本文件更新了, 这里是下载地址链接: http://antognini.ch/top/downloadable-files/.

    供参考: 我的学习方法是这样的,先读完整本书(每周100页), 然后到附录A, 顺着每一章的脚本目录(page 552~562) ,做练习,依靠实践加深印象,巩固记忆.不然,过不了两天,学到的知识点就会忘掉大半.


    加拿大西海岸三月份又下雪了,维多利亚市也不例外,预计降雪量是5厘米.
    气温: -4°C~2°C. 注意保暖,行车注意安全.
    今天又开始夏时制了,少睡一个小时, 困哉.
    .

    Thursday, March 05, 2009

    Index space management索引空间管理

    这回咱先问个问题, 啥时候数据库自动回收索引的空闲空间?

    这里是我昨天学到的索引空间管理知识:

    一个UPDATE语句,对索引来说,就是一个DELETE和一个INSERT,删掉旧键值,插入新键值.
    如果是唯一索引(unique index),删掉旧键值的空槽位可以被同一个事务里面接下来的操作重用.
    如果不是唯一索引(unique index),删掉旧键值的空槽位,只有在事务提交以后,才可以被重用.
    索引段上,只有INSERT和DELETE操作.

    如果删除了大部分数据,再没有新的数据插入,用alter index coalesce;释放可重用的空间. coalesce应该不会锁住表,我需要进一步确认.

    参考
    ----
    Oracle® Database SQL Language Reference
    11g Release 1 (11.1)

    ALTER INDEX ... SHRINK SPACE COMPACT 等价于 ALTER INDEX ... COALESCE.

    How does insert and delete use space regarding to indexes?

    查看索引空间: SQL>exec segment_space_a(P_SEGNAME=>'INDEX_Name',p_type=>'INDEX');

    Skip unchanged columns when UPDATE时,如何跳过没有改动的列

    现在很难在 AskTom 提新的问题了.
    只好找个类似的问题,然后跟贴评论,问一个新问题. 但是一定要和原帖主要问题紧密相关,不然,Tom兄会毫不留情的删掉你的评论. 嘻嘻.

    好了,我的问题是:
    http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1524420700346152252

    先简述一下业务逻辑, 我们的业务模式类似eBay, B2C, 我们的主要商品是图书, table book, 书商每天上传文件更新他们的库存.
    书商不管三七二十一,送上所有图书的信息,无论是要改动的属性,还是不需要改动的属性.
    大部分情况只是改动一两个短列,比如数量,单价,ISBN;少部分情况修改长列,比如书名,作者,出版社,图书简介...等等.
    这就产生了一个重复(冗余)修改的问题,会浪费PGA内存,产生十倍之多的Redo/Undo.

    如何跳过这些没有修改的列呢?

    今天耗费了一整天跟Tom兄切磋.

    我设计的解决方案都在上面链接里面了. 还没有最后成形,处在演变进化(evolution)当中.

    对了, 我的署名是Charlie MuJiang from Victoria, BC Canada, AskTom不能存中文,所以用拼音MuJiang.


    再来一个维多利亚的BC省议会大楼,2005年我刚到维多利亚时,住的公寓走到议会大楼不到十分钟,每周过来散步数次.

    Monday, March 02, 2009

    PATH in 10053 Trace 的存取路径代码和解释

    越来越多的DBA和Developer开始研究CBO相关的10053 Trace.
    可以参考老刘(Lewis)的Cost Based Oracle Fundamentals第14章 - The 10053 Trace File.

    Oracle 11g之前,PATH 用代码表示,阅读起来极不方便, 因此木匠干脆罗列出来有关表扫描的Access PATH代码含义:

    # PATH in 10053 trace
    -- table access path


    0 parallel hint
    1 no access path spec
    2 table scan
    3 index unique
    4 index range
    5 index and-equal
    6 order by using an index
    7 open cluster
    8 hash cluster
    9 rowid lookup
    10 range scan backwards
    11 rowid range scan
    12 driving_site hint
    14 cache hint
    15 nocache hint
    16 partitions hint
    17 nopartitions hint
    18 anti-join
    19 index rowid range scan
    20 bitmap index
    21 parallel_index hint
    22 noparallel_index hint
    23 index fast full scan
    24 swap inputs to join
    25 fact table
    26 not a fact table
    27 merge of this view
    28 do not push join predicate into this view
    29 push join predicate into this view
    30 no_merge of this view
    31 semi-join

    Thursday, February 26, 2009

    虚拟列分区可能返回错误结果Virtual Column-Based Partition-Chris译客

    TrackBack: http://antognini.ch/2009/02/virtual-column-based-partitioning-might-lead-to-wrong-results/

    Oracle 11g(11.1.0.6 和 11.1.0.7),在虚拟列分区表里面,有许多列,当虚拟列或者源数据列排在后面时,修改数据和查询数据会产生意想不到的错误结果.
    出错的情况是随机的, 比如数据被放进了错误的分区, 或者查询数据,返回错误结果

    这里是测试用例:

    SQL>
    drop TABLE t;
    CREATE TABLE t (
    d1 NUMBER,
    d2 NUMBER,
    d3 NUMBER,
    d4 NUMBER,
    d5 NUMBER,
    d6 NUMBER,
    d7 NUMBER,
    n1 NUMBER,
    n2 AS (CASE n1 WHEN 1 THEN 1 WHEN 2 THEN 2 ELSE 0 END) VIRTUAL
    )
    PARTITION BY LIST (n2) (
    PARTITION zero VALUES (0),
    PARTITION one VALUES (1),
    PARTITION two VALUES (2)
    )
    ENABLE ROW MOVEMENT;

    INSERT INTO t (n1) VALUES (1);
    commit;
    UPDATE t SET n1 = 3;
    commit;

    SELECT rowid, n1, n2 FROM t PARTITION (zero);
    SELECT rowid, n1, n2 FROM t PARTITION (one);

    数据被放进了错误的分区.
    SQL> SELECT rowid, n1, n2 FROM t PARTITION (one);

    ROWID N1 N2
    ------------------ ---------- ----------
    AAAd7XAAEAAABXCAAA 3 0


    查询数据,返回错误结果
    SQL> SELECT rowid, n1, n2 FROM t WHERE n2 = 1;

    ROWID N1 N2
    ------------------ ---------- ----------
    AAAd7XAAEAAABXCAAA 3 0



    昨天在内港Delta酒店参加领导能力培训,南望华盛顿州,奥林匹亚山.