2.4 位图索引

    位图索引主要用于决策支持系统或静态数据,不支持行级锁定。位图索引最好用于低cardinality列(即列的唯一值除以行数为一个很小的值,接近零),例如又一个“性别”列,列值有“Male”,“Female”,“Null”等3种,但一共有300万条记录,那么3/3000000约等于0,这种情况下最适合用位图索引。

    位图索引可以是简单的(单列)也可以是连接的(多列),但在实践中绝大多数是简单的。在这些列上多位图索引可以与AND或OR操作符结合使用。位图索引使用位图作为键值,对于表中的每一数据行位图包含了TRUE(1)、FALSE(0)、或NULL值。位图索引的位图存放在B-Tree结构的页节点中。B-Tree结构使查找位图非常方便和快速。另外,位图以一种压缩格式存放,因此占用的磁盘空间比B-Tree索引要小得多。

    如果搜索where gender=’Male’,要统计性别是”Male”的列行数的话,Oracle很快就能从位图中找到共3行即第1,9,10行是符合条件的;如果要搜索where gender=’Male’ or gender=’Female’的列的行数的话,也很容易从位图中找到共8行即1,2,3,4,7,8,9,10行是符合条件的。如果要搜索表的值的话,那么Oracle会用内部的转换函数将位图中的相关信息转换成rowid来访问数据块。

    2.5 函数索引

    基于函数的索引也是8i以来的新产物,它有索引计算列的能力,它易于使用并且提供计算好的值,在不修改应用程序的逻辑上提高了查询性能。使用基于函数的索引有几个先决条件:

    (1)必须拥有QUERY REWRITE(本模式下)或GLOBAL QUERY REWRITE(其他模式下)权限。
    (2)必须使用基于成本的优化器,基于规则的优化器将被忽略。
    (3)必须设置以下两个系统参数:

    QUERY_REWRITE_ENABLED=TRUE
    QUERY_REWRITE_INTEGRITY=TRUSTED

    可以通过alter system set,alter session set在系统级或线程级设置,也可以通过在init.ora添加实现。这里举一个基于函数的索引的例子:



SQL
  
  >
  
   
  
  create
  
   
  
  index
  
   test.ind_fun 
  
  on
  
   test.testindex(
  
  upper
  
  (a));
    索引已创建。
    SQL
  
  >
  
   
  
  insert
  
   
  
  into
  
   testindex 
  
  values
  
  (
  
  '
  
  a
  
  '
  
  ,
  
  2
  
  );
    已创建 
  
  1
  
   行。
    SQL
  
  >
  
   
  
  commit
  
  ;
    提交完成。
    SQL
  
  >
  
   
  
  select
  
   
  
  /**/
  
  /*+ RULE*/
  
  *
  
   
  
  FROM
  
   test.testindex 
  
  where
  
   
  
  upper
  
  (a)
  
  =
  
  '
  
  A
  
  '
  
  ;
    A B
  
  --
  
   ----------
  
  
  
      a 
  
  2
  
  
    Execution 
  
  Plan
  
  
  
  --
  
  --------------------------------------------------------
  
  
  
      
  
  0
  
   
  
  SELECT
  
   STATEMENT Optimizer
  
  =
  
  HINT: 
  
  RULE
  
  
  
  1
  
   
  
  0
  
   
  
  TABLE
  
   ACCESS (
  
  FULL
  
  ) 
  
  OF
  
   
  
  '
  
  TESTINDEX
  
  '
  
  
    (优化器选择了全表扫描)
  
  --
  
  ------------------------------------------------------------------
  
  
  
      SQL
  
  >
  
   
  
  select
  
   
  
  *
  
   
  
  FROM
  
   test.testindex 
  
  where
  
   
  
  upper
  
  (a)
  
  =
  
  '
  
  A
  
  '
  
  ;
    A B
  
  --
  
   ----------
  
  
  
      a 
  
  2
  
  
    Execution 
  
  Plan
  
  
  
  --
  
  --------------------------------------------------------
  
  
  
      
  
  0
  
   
  
  SELECT
  
   STATEMENT Optimizer
  
  =
  
  CHOOSE (Cost
  
  =
  
  2
  
   Card
  
  =
  
  1
  
   Bytes
  
  =
  
  5
  
  )
  
  1
  
   
  
  0
  
   
  
  TABLE
  
   ACCESS (
  
  BY
  
   
  
  INDEX
  
   ROWID) 
  
  OF
  
   
  
  '
  
  TESTINDEX
  
  '
  
   (Cost
  
  =
  
  2
  
   Card
  
  =
  
  
  
  1
  
   Bytes
  
  =
  
  5
  
  )
  
  2
  
   
  
  1
  
   
  
  INDEX
  
   (RANGE SCAN) 
  
  OF
  
   
  
  '
  
  IND_FUN
  
  '
  
   (NON
  
  -
  
  UNIQUE
  
  ) (Cost
  
  =
  
  1
  
   Car
    d
  
  =
  
  1
  
  )(使用了ind_fun索引)

     3 各种索引的创建方法

    (1)*Tree索引。
    Create index indexname on tablename(columnname[columnname...])
    (2)反向索引。
    Create index indexname on tablename(columnname[columnname...]) reverse
    (3)降序索引。
    Create index indexname on tablename(columnname DESC[columnname...])
    (4)位图索引。
    Create BITMAP index indexname on tablename(columnname[columnname...])
    (5)函数索引。
    Create index indexname on tablename(functionname(columnname))
    注意:创建索引后分析要索引才能起作用。
    analyze index indexname compute statistics;

    4 各种索引使用场合及建议(1)B*Tree索引。

    常规索引,多用于oltp系统,快速定位行,应建立于高cardinality列(即列的唯一值除以行数为一个很大的值,存在很少的相同值)。
    (2)反向索引。
    B*Tree的衍生产物,应用于特殊场合,在ops环境加序列增加的列上建立,不适合做区域扫描。
    (3)降序索引。
    B*Tree的衍生产物,应用于有降序排列的搜索语句中,索引中储存了降序排列的索引码,提供了快速的降序搜索。
    (4)位图索引。
    位图方式管理的索引,适用于OLAP(在线分析)和DSS(决策处理)系统,应建立于低cardinality列,适合集中读取,不适合插入和修改,提供比B*Tree索引更节省的空间。
    (5)函数索引。
    B*Tree的衍生产物,应用于查询语句条件列上包含函数的情况,索引中储存了经过函数计算的索引码值。可以在不修改应用程序的基础上能提高查询效率。