木匠的微型博客 Charlie Twitter

    follow me on Twitter

    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酒店参加领导能力培训,南望华盛顿州,奥林匹亚山.

    Tuesday, February 24, 2009

    SQL跟踪文件里面哈希值的变化 - 启动TOP作者博客翻译

    TrackBack: http://antognini.ch/2009/01/execution-plan-hash-value-in-sql-trace-files/

    在征得了Christian Antognini的同意后, 木匠准备近乎实时的(near real-time)跟踪报道他的最新研究成果. 附带的好处是极大的增加了我的博客出版频率,完成年初定的每周一篇技术贴的目标.

    在我理解有误的地方,欢迎各位DBA同仁给予指正. 木匠没有出钱买断Christian Antognini博客的中文翻译版权, 所以您也可以同时翻译相同的文章, 不过, 请一定指明原文的TrackBack.

    我只会讲每篇的主旨和总结. 从2009年一月开始,

    第一篇: SQL跟踪文件里面哈希值的变化(Execution Plan Hash Value in SQL Trace Files)

    在Oracle 11.1.0.7版本, 在PARSE, EXEC 和FETCH这些行里边, 新出现了一个"plh"属性, 我猜是 Plan Hash 的缩写. plh是为了配合ACS(Adaptive cursor sharing), ACS就是根据不同的绑定变量(binding variable)产生不同的最优执行计划.

    参见 http://antognini.ch/2008/12/automatic-evolution-of-sql-plan-baselines/ 第7个木匠的注释.

    这里是一个SQL trace file样例,

    SELECT count(pad) FROM t WHERE id < :id

    PARSE #13:c=0,e=0,p=0,cr=0,cu=0, mis=0,r=0,dep=0,og=1,plh=4270555908
    EXEC #13:c=0,e=0,p=0,cr=0,cu=0, mis=1,r=0,dep=0,og=1,plh=2966233522

    当变量取值发生变化后,优化器决定选择一个不同的执行计划. 我们看到mis=1和plh=2966233522 出现在EXEC(执行)这一行,而且的plh数值不同于PARSE一行plh的数值 SQL优化器对游标(cursor)做了一个硬解析(hard parse), 然而PARSE部分没有硬解析.

    由此改变了我们的传统认识, 不但PARSE部分会hard parse,而且EXEC部分也会hard parse.


    去阿拉斯加的邮轮,在维多利亚Ogden Point港停靠.

    Friday, February 20, 2009

    US vs Canada一位大姐眼中的美国和加拿大

    导读: 已经有很多文章比较了美国和加拿大的华人生活.

    这篇就比较片面, 居住在加拿大的木匠不免要运用一下精神胜利法,分析一下她的论点.

    1. 由于她在加拿大年景差,做了4年家庭主妇,潜意识里对加拿大产生了怨恨.
    - 如果2001~2004年她住在美国, 2005~2009年她住在加拿大,肯定有不一样的感受.
    2. 由于接触面窄,没能对加拿大华人有一个全面的了解.
    3. 我们公司华人同事的年薪均高于美国相同职位.
    4. 美国枪击案件远远超过加拿大, 安全吗?
    5. 加拿大人朴实,憨厚,资源性国家,生活节奏缓慢,惬意舒坦,平均寿命长,生活满意度高.
    6. 美国华人会对加拿大华人提出这样一些(极其片面)问题:
    • 来美国玩吧,我们这里有唐人街.
    • 你们(比如多伦多)出门上街,是不是能撞上北极熊?
    7. 大陆华人很难直接移民美国,除了走留学这条弯路,没别的办法. 所以好多华人学了洋人没兴趣的偏门专业,多数肯定不是自愿的.
    8. 加拿大的社会福利,医疗保障优于美国.
    9. 加拿大中产阶级人群收入低,生活成本高,税收高.
    - 加拿大老百姓平均收入高于美国; 不能老拿东海岸纽约/波士顿和西海岸硅谷湾区说事.
    10. 加拿大最低时薪高于美国.
    11. 移民加拿大后进出自由,五年内住满两年就可以了; 可是在美国, 留学(F1)和工作(H1b)后, 轻易不敢回中国, 不然要丢身份(证)的, 由此引发了不少和父母生离死别的悲惨故事,改天再议.

    总之,若以居住在月球/火星的华人来看的话, 不管搬到美国还是加拿大,都是想过上好生活,等中国富裕强大了,到美国/加拿大只需要落地签证,就不会有那么多华人削尖了脑袋移民美国/加拿大了. 祝福我们的祖国吧.

    我们都是这个时代的特殊产物,以后历史再不会重演,留学美国或者技术移民加拿大只会成为一个历史名词.

    ...未完待续...



    正文

    -- -- -
    http://news.wenxuecity.com/messages/200902/news-gb2312-797788.html

    本人从中国出来后曾先后在加拿大几个不同的城市共居住了四年,然后移居美国中部近四年,对新移民在二个不同国家作了一些比较,体会如下:

      1. 年龄

      一般来说,加拿大移民的年龄偏小一些,多数是90年代后期移民出来的人,年龄在30--40岁左右。而美国移民则年龄偏大一些,多数是80年代后期及90年代前期出来的,这批人年龄多已40出头了。当然也有一批幸运者,他们在30岁前就直奔美国,在这里30而立了。

      2. 技术实力

       我相信在美国的移民都会感到他们自己是各自公司或部门技术上的骨干,事实也基本如此。因为到美国的人,多数是走读书这条路的,尤其是早期出来的人,他们 本身就是国内出类拔萃的人物,到美国后艰苦奋斗,几年后几乎都持有博士学位,最起码也拿个硕士,即便是女的,博士,硕士也比比皆是。他们凭着挣来的学位, 进入各自的公司或大学,凭着他们的聪明以及读书几年闯过的各种关卡,尤其是语言关,大多能够顺利地胜任自己的高薪工作。

      回头看一 看加拿大,在加国的一部分早期留学生有着和美国移民相似的经历,他们的生活也还自在。但大批新移民却没有踏上读博这条“苦船”,他们偏于急功近利,他们比 “长辈”有较多的选择,他们可以利用国内的经验直接进入国外公司。也有迫于生计,选取短,平,快的学业,快速找到了工作,但他们多数难以进入技术“上层 ”,即便工作几年后,也较难得到像美国移民们苦熬几年学业出来的高薪。

      3. 居住

      居住环境的好坏直接反映 出移民的经济实力。由于美国移民的技术实力较强,相应他们的收入便偏高些。我周围的朋友,只要夫妇一方博士毕业,年薪基本是八万以上,这已步入当地中产以 上阶层,更不用说双方都是高学位了。我居住的这个城市中国人不少,主要集中在几个大公司和学校工作。他们几乎都是“一栋房子二部车”一族了。他们大多居住 条件不错,生活比较稳定。拿我本人来说,我的居住环境在我的一批朋友中是属中等的。因为我只持有国内本科文凭,在加拿大时属 “急功近利”一族,没有读学位,来美后由于身份问题,不能工作,后来身份解决了,有了工作,但终究薪水不高,主要靠先生的收入买房。我们量力而行,在较好 的学区内建了一栋不到30万的房屋。二年多前,我们搬进了在新开发小区内的新居。我们小区内住了几十户中国人,个个都对自己的居住条件满意,大家觉得来美 国生活,衣,食,住,行,唯有这“住”还使我们对这里有些留恋,不思“海归”。正当我为自己五个睡房的住宅陶醉时,我的好朋友(她十年前移民来美国)在离 我不远的富人区,一举建造了价值130万的住宅。这在美国中部地区就算“豪宅”了,绝对进入当地居住的上层。

      再看看加拿大的朋 友,他们多数还没有买房,因为有一部分人想往美国走,即使买了房,他们的居住条件也相对小一些。我曾在加拿大的一个小城镇居住过,虽然小城镇的房价偏低, 但也不表示人们住大房子。我的朋友,即使是我公司的老板也居住着比我现在还小的房子。而对于多伦多周围的住房,那就更小一些了。我去过一个朋友在离多伦多 一小时远的城市买的一栋新房,新房在一片新开发区内,给人的感觉是房子比较密集,房子也比较小。

      4. 心境

       美国的移民,由于他们早年的奋斗,现在多数已是苦尽甘来。他们大多已解决身份,生活平静,安居乐业。他们也很忙,忙于工作,忙于培养小孩。闲暇时考虑室 内,室外的改造。夏天更可以看见他们忙碌于前院后院的身影。他们经常聚在一起吃饭,打牌。他们更看国内的新连续剧,新电影,好多国内朋友都没听过名字的电 视剧,在这里已经传得热火朝天了。当然他们也不乏各式各样的烦恼,如何使自己的生活更上一层楼, 如何使自己的奋斗更具价值,“海归”,办公司,小孩读私校, ……… 他们有很多想法。

      而加拿大的移民,则显得要浮躁些。因为他 们当中很多人还有美国梦。他们觉得凭着在加拿大的工作经验,完全有能力在美国得到更好的发展。加拿大的冬天让他们不愿意在那里扎根,他们的目标是美国。而 美国的移民政策难度比加拿大难,这些身份问题会让他们感到心烦。另外,加拿大移民比较愿意了解美国移民的信息,而美国移民对加拿大移民的情形却不太关心。 就像在美国电视里很难见到有关加拿大的新闻一样,他们显得对加拿大比较漠然。加国移民的心情没有那么靚,因为他们还在爬坡,还有很多愿望等着他们去实现。