Monthly Archives: January 2010

滥用Session级变量的后果

目前只想到两个后果,以后再补充

1.无法确定何时从session中移除这个变量。 在一系列操作的最后一步时去除?不行,用户可能做了一半就不做了。那,就不移除又怎么样? 答案是会有灾难性的后果,用户会看到莫名奇妙的东西,同时程序员很难复现这种问题。

2.无法确定何时把变量植入到session中。一般认为在“操作系列”的第一步时植入就够了,但其实每个中间步骤在未来都可能变成另一个“操作系列”第一步。到未来再说? 未来的程序员就是另一个人了,他根本不知道原始“操作系列”的存在!

[随想] 上下层互相依赖到底有什么后果?

答: 影响了下层模块的可重用性。由于下层依赖上层的某个模块,当上层的另一个模块需要调用该下层模块时,那就会发现这个下层无法直接调用。

举个例子。比如 某个Service模块需要读取“操作者”以判断权限。第一次写代码时,为了贪图方便,就直接在Service里读取 Session.getUser()获得“操作者” 。后来来了新需求,某个Web服务也要调用这个Service,那这样就会出问题了。

Notes on ‘Expert Oracle’ — No.10.4: Table — Nested table & Temp table

Nested Table

  1.Can be used for persistence or PL/SQL programming, but mainly used for programming.

  2.Can be used as the type of another table’s column

  3.Can’t referece any table for constraints, including itself.

Temp Table:

   1.There is no concurrency problem for temp tables.  Because two sessions will never share one copy.

   2.Oracle’s temp table is staticly-defined structure. You can’t expect to create/drop freely it in your programs.

   3.The data can retain inside a transaction, or inside a session(Spanning-transaction).

   4.Shortcomings

      a.Can’t be used as the target of any foreign key

      b.Can’t be analyzed => It will do harm to performace if CBO(cost-based optimizer) is used.

   5.Try to avoid use temp-tables.

      a. You can use INLIN-VIEWS for temp data. Select * from (select * from XXX), e.g.

      b.If you have to use temp-table, try to give hints to CBO by "select /*first_low*/ * from temp_table", or use "DBMS_STATS" to help CBO.

为了单元测试,我觉得程序中应该大量采用“支持链式调用”的setter

所谓链式的setter 就是 

   bean.setProp1("1").setProp2("2")…setPropN("N")

这样的好处就是:一行代码就可以设置完尽量多的属性值。这在单元测试里特别有用。

举例来说,当你要设置一个Bean作为测试数据,如果不用链式,则

    Bean bean = new Bean();
    bean.setProp1("1");
    bean.setProp2("2");
    bean.setProp3("3");
    assertEquals("XXX", bean.getXXX()); 

   一共要写五行代码。

    1. 由于普通的Setter不支持链式调用,因此3个属性要写3行set语句,每条语句里都要写一个"bean"字,即12个字母;

    2. 另外,构造方法 new Bean()本来是链式的,但由于受到无链式setter的拖累,以致于必须显式地声明一个 "bean" 变量。

而如果我们用链式风格的setter的话,一行即可。

   assertEquals("XXX",new Bean().setProp1().setProp2().setProp3().getXXX())); 

   看,多简洁! 可以采用匿名对象(new Bean()),并且不用换行。

当然了,这样做的好处主要是为了单元测试时准备数据。正式代码里可能不会一次性设置这么多属性,就算要设置这么多,这样写也会降低代码的可调试性。

你可能会问为什么不用一个 带有所有参数的构造方式? 我的看法是,

   1.参数较多的构造方法比较丑陋,调用时也容易把参数顺序搞错。比如 new Name("Diego", "Maradona") 中,哪个是 first name, 哪个是 last name?

   2.写带参构造方法比写无参和要累

   3.最重要的是,新增属性时会使带参的构造方法不得不重构。很烦。

Notes on ‘Expert Oracle’ — No.10.3: Table — 聚簇表

1.引子

问题:我经常连接表A和表B,除了建立表索引外吗,还有别的优化手段吗?

答案:有。如果A和B相应的一组数据在同一个块中,那么查询时就不需要取出那么多块了,I/O效率会高很多。

2.什么是聚簇

  a. A和B的同组数据放在同一个块中,如果A和B经常连结

  b. 同一张表中共享同一列值的行尽量放在同一个块中

3.一个聚簇块应该放几行数据?

  要恰当地设置这个值。

    a.如果行数太少,则会浪费块的空间

    b.如果行数太多,则可能会导致 块 不能容纳整行数据,而只能通过串链解决问题。串链太多就适得其反了。

4.什么时候应该用聚簇

   以读为主、且主要使用索引读、并且经常要进行连接查询的一组表应该放在同一个聚族中。

Notes on ‘Expert Oracle’ — No.10.2: Table — HOT & IOT

1. HOT => Heap Organized Table

   IOT => Index Organized Table

2.HOT

  Heap Organzied

3.IOT

  a.The data is index Organized

  b.The data is the index, the index is the data

     i.No extra cost for managing index

    ii.When you get the index, you get the data. No "table access" is needed in querys.

   iii.Related data will be put together => Fewer blocks are accessed for queries aimed for related data => Less I/O

  c.Parameter: NOCOMPRESS/COMPRESS

    i.NOCOMPRESS: Every combination of the value of indexed-columns requires an occupation in the storage. <abc,1> and <abc,2> will need 2*2 rooms

   ii.COMPRESS N: <abc,1> and <abc,2> will be stored as <abc>, <1>,<2> = 3 rooms.

      Less room => more data in a block => Fewer blocks needed => Less I/O

  d.Overflow Segment

     Q: Where does Oralce put non-indexed row data?

     A: It may be put in index-blocks along with the indexed keys, or put in an "Overflow" segment if its size is too large.

     Q: How does Oracle decide where to put then?

     A: Oracle can refer to PCTTHRESHOLD for a max percentage, or check "INCLUDING" to see which columns should be retained in index blocks.

Notes on ‘Expert Oracle’ — No.10.1: Table — Segment Space Management

1. Tow modes of Segment Space Management

   a. Automatic — ASSM

   b. Manual    — MSSM

We only care about ASSM here.

2.High-water Mark

2.1 What is it for ?

Question:  I’ve deleted all the data from the table by using "delete from …". Why does "select count(*) from …" take a long time?

Answer: There is a High-water Mark (HWM) in each table.
HWM rises as rows are added. But it doesn’t fall as rows are deleted, and the blocks are still there though empty.

  So, even if the delete all the data, a full-table access like "select count(*)" will still acess all the blocks.

2.2 How does ASSM deal with it?

  Some blocks under HWM represent some data, some don’t under, such as deleted rows.  If we can decide which blocks are empty-blocks and which are not, then performance will be better.  

  
There will be a Low HWM in in ASSM under which all rows are "real blocks" which  should be accessed.

3. Row Migration & PCTFREE

3.1 Why migrat a row?

   a. If a row’s size is going to increased so much that current block doesn’t have enough space for it, then the row has to be migrated to another row, in a whole or partically.

   b. However, in the original block, there will be a pointer to the new block.

3.2 Anything bad about Row Migration?

    A Row spans blocks => Caching more than one block => Performance Issues

3.3 How to deal with problem?

   Let the block always have a faily enough free space by setting PCTFREE, such as 40%

  
If the size of row may be increased significantly => Set large PCTFREE   

   Otherwise => Set small PCTFREE

4. INITTRANS

   INITTRANS = INITTRANS of a block

   The number of transactions allowed on the same block. There will be waiting if this value is too low.