Monthly Archives: February 2010

Notes on ‘Expert Oracle’ — No.13.3: 分区 — 索引分区

索引分区的两种模式

   1.表分区 =>相应地 索引分区。表分区A对应索引分区A,表分区B对应索引分区B。这叫“局部索引分区”

   2.独立于表分区,对索引进行分区。 分区以后,索引分区A中可能既有 表分区A某些行的条目,又有表分区B某些行的条目; 同样,表分区A中可能有些数据的条目在索引分区A中,又有些数据的条目在索引分区B中。 这叫“全局索引分区”

Notes on ‘Expert Oracle’ — No.13.2: 分区 — 分区机制

Q:按什么分区呢?

A:四种方案

   1.按数值区间分。如 [1-100]放A区,[101-200]放B区

   2.按枚举值对离散值进行分区,如 [江西,福建] 放A区,[北京,浙江]放B区。 这叫“列表分区”

   3.直接按散列值分区。这没啥好说的。

   4.综合使用以上几种分区机制进行多次分区,在大分区里再分成小分区。

Q:数据不会在分区之间迁移吧?

A:会。

   1.比如 原来有条记录值为 1,放在A区;现在它的值变成了105,就必须移到B区了。

   2.这种“行移动”的开销很大。如果你选择的分机机制导致这种事情经常发生,那就是失败的分区

Notes on ‘Expert Oracle’ — No.13.1: 分区 — 分区的好处

1.提高系统的可靠性(HA): 不把所有的鸡蛋放到同一个篮子里

   a.分区A坏了,但分区的B数据仍然可以被查询到

   b.分区A坏了,恢复这个分区的时间比恢得整张表的时间要短得多

2.减少管理负担。 比如说,重建某个分区的索引比重建整张表的索引要轻松的多

3.SQL的性能

   a.在较早版本的Oracle中,想要执行“PDML”(一种并行执行DML的机制),就必须对表进行分区

   b.可以提升OLAP系统的查询。 因为OLAP的查询一般都是大批量查询,不用索引,而是进行“全面扫描”。分区前,需要全表扫描;分区后,可能只需对某一个区进行全面扫描。

   b.基本不能提升OLTP系统的查询速度,甚至可能更慢。

      i.查询基于索引。分区前,在大索引中查询;分区后,在小索引中查询。这两种查询的速度是一样的。

     ii.甚至可能更慢。因为现在可能要查好几个索引,产生更多I/O。

   c.对OLTP的DML操作可能有好处

      i.因为这样可以减少数据竞争和索引竞争的机率

     ii.但是仍有额外开销:插入新行时,需要判断把它放在哪个分区。

Notes on ‘Expert Oracle’ — No.12.3: 数据类型 — Date/Time类型

1.查询时,尽量避免在日期类型的字段上使用函数

   a.因为这会使该字段上的索引失效。比如说

        坏:select … where to_char(birthday) = ‘2010-1-1’

        好:select … where birthday     = to_date(‘2010-1-1’)

   b.如果非用不可,可以考虑一下是不是可以不用 to_char,而只用 trunc就可以了?因为trunc函数的性能要好得多。比如说,

       坏: select … where to_char(birthday, ‘YYYY’) = ‘2005’

       好: select … where trunc(birthday, ‘y’) = to_date(‘1-1-2005’)

2. Date V.S. Timestamp

 

   Date只能精确到“秒”

   而Timestamp可以精确到 10的-9次方秒

Notes on ‘Expert Oracle’ — No.12.2: 数据类型 — 数字类型

1.一般都用"Number"这个类型

2.数据库如何处理精度超出定义的输入数据?

  a.舍入: 小数位过多,但整数位未超标,则为小数位作四舍五入并插入数据库

  b.拒绝并报错: 整数位若超标,则直接拒绝

3.Number类型 V.S. Float/Double类型

  a.Number类型更准确

  b.在做数学计算时,Float/Double的性能更高,因为它是基于硬件的计算,而Number是基于软件的计算。不过Float/Double数学计算的准确度较差。

  c.可以将字段存为Number类型,在需要数学计算时,临时cast为Float/Double类型

Notes on ‘Expert Oracle’ — No.12.1: 数据类型 — 字符类型

1.注意字符集的设置,即NLS

2.char/nchar根本就用不上

  i.它会通过空格填补空余空间,造成空间浪费

ii.它还会导致  select … where column_five_char = ‘ABC’ 打不到记录,因为 数据库里存的不是 ‘ABC’,而是 ‘ABC  ‘

3.设置varhcar2的宽度时要注意:宽度有两种单位,一为 byte 类型,另一为 char 类型

   在非西文应用中,可以使用 char作为宽度单位,因为你的需要注一般是 “姓名不能超过50字符”,而不是“姓名不能超过50字节”

4.如果用 nvarchar2的话,那它的宽度单位固定为 char

Notes on ‘Expert Oracle’ — No.11.4: 索引 — Tips

1.B* 索引不会为 全null 值建立索引条目

   所以 select * from T where x is null 不会使用索引 (如果索引建在x字段上)

   不过, 如果满足以下两个条件, 仍会用到索引

       a. 索引建在 (x,y) 上

       b. y 被定义为Not Null字段

2. 外键上要不要索引?

   a.一般来说都要,否则的话

     i.如果修改父表的主键值或者删除父表中一行记录,会导致整个子表被锁

    ii.父表中的On Delete Cascade被触发时 也会导致全表扫描

   iii.按父表中的值查询子表记录时,由会导致对子表的全表扫描

   b.相反地,如果同时满足以下所有条件,就不用加索引  

     i.不会修改父表主键值且不会删除父表记录

     ii.不存在从父表到子表的连接

3.为什么我的索引没有被用上?

   i. 索引建在 (x,y)复合字段上,但查询谓词只查了x

  ii. select count(*) … 本来用索引就够了,但是如果存在null的数据值,优化器就不敢依赖索引来回答这个查询,因为null值没有索引条目

iii. select … where f(x) = value  不会使用建立在x上的索引,不过它会使用建立在f(x)上的索引

iv. select … where string_column = 5 不会使用索引,因为它实质上是,

      select … where to_number(string_column) = 5 //这是一个基于函数的查询

  v. 需要返回很多行 => 用索引的效率还不如全表扫描的效率

   

Notes on ‘Expert Oracle’ — No.11.3: 索引 — BitMap 索引

BitMap 索引

  1.基本上用于OLAP,一般不适用于OLTP环境

  2.结构

     BitMap Index:  一个索引条目对应多行

     B* Index: 一个索引条目只对应一行

  3.一个条目对应多行 => 因此只适用于 Distinct Cardinality 较低的情况,比如“性别字段”只有M/F这两种取值

  4.不适用于“并发写”很频繁的场合。锁住一行数据 => 锁住整个索引条目 => 锁住该条目下的所有数据行 => 并发性极弱

BitMap Joined Index

  1.也是BitMap索引的一种

  2.只不过表A的索引建在表B的某个字段上,这样可以提升连接查询的效率。

Notes on ‘Expert Oracle’ — No.11.2: 索引 — B*索引

1.结构

  a.类似于二叉树

  b.高度平衡:所有叶结点都在树的同一层次上

  c.一般来说高度是2或者3 (需要2至3次I/O)

2.When B*?

  a.如果与索引有关的查询只返回少数几行数据,则可以用B* 索引

  b.如果与索引有关的查询会牵涉到多行数据,但索引本身就可以回答这类查询(如 select count(*)),则也可以用B*索引。